Learning Android: Freezing the UI with a BroadcastReceiver

As I mentioned in a previous post I recently wrote some code in my Android app to inform a BroadcastReceiver whenever a service processed a tweet with a link in it but in implementing this I managed to freeze the UI every time that happened.

I made the stupid (in hindsight) mistake of not realising that I shouldn’t be doing a lot of logic in BroadcastReceiver.onReceive since that bit of code gets executed on the UI thread.

The service code which raises the broadcast message is the same as in the previous post:

public class TweetService extends IntentService {
    ...
    @Override
    protected void onHandleIntent(Intent intent) {
        StatusListener listener = new UserStreamListener() {
           // override a whole load of methods - removed for brevity
 
            public void onStatus(Status status) {
                String theTweet = status.getText();
                if (status.getText().contains("http://")) {
                    Intent tweetMessage = new Intent(TweetTask.NEW_TWEET);
                    tweetMessage.putExtra(android.content.Intent.EXTRA_TEXT, status.getText());
                    sendBroadcast(tweetMessage);
                }
 
            }
        };
 
        // code to connect to the twitter streaming API
    }
}

That is then handled like this by the BroadcastReceiver:

public class MyActivity extends Activity {
    protected void onPause() {
        super.onPause();
        if (dataUpdateReceiver != null) unregisterReceiver(dataUpdateReceiver);
    }
 
    protected void onResume() {
        super.onResume();
        if (dataUpdateReceiver == null) dataUpdateReceiver = new DataUpdateReceiver();
        IntentFilter intentFilter = new IntentFilter(TweetTask.NEW_TWEET);
        registerReceiver(dataUpdateReceiver, intentFilter);
    }
 
    private class DataUpdateReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(TweetTask.NEW_TWEET)) {
                Pattern p = Pattern.compile("(http://[^\\s]+)");
                String theTweet = intent.getStringExtra(TweetTask.NEW_TWEET);
                Matcher matcher = p.matcher(theTweet);
 
                int startIndex = -1;
                int endIndex = -1;
                while (matcher.find()) {
                    startIndex = matcher.start();
                    endIndex = matcher.end();
                }
 
                if (startIndex != -1 && endIndex != -1) {
                    String resolvedUrl = resolveUrl(theTweet.substring(startIndex, endIndex));
                    saveToDatabase(resolvedUrl);
                    updateUI(resolvedUrl);
                }
            }
        }
    }
}

In particular the ‘resolveUrl’ line was probably the one one causing the problem since it makes a network call to resolve URLs from link shorteners.

To stop the screen freezing up I just needed to move most of the code from BroadcastReceiver into the TweetService:

public class TweetService extends IntentService {
    ...
    @Override
    protected void onHandleIntent(Intent intent) {
        StatusListener listener = new UserStreamListener() {
           // override a whole load of methods - removed for brevity
 
            public void onStatus(Status status) {
                String theTweet = status.getText();
                if (status.getText().contains("http://")) {
                    Pattern p = Pattern.compile("(http://[^\\s]+)");
                    Matcher matcher = p.matcher(theTweet);
 
                    int startIndex = -1;
                    int endIndex = -1;
                    while (matcher.find()) {
                        startIndex = matcher.start();
                        endIndex = matcher.end();
                    }
 
                    if (startIndex != -1 && endIndex != -1) {
                        String resolvedUrl = resolveUrl(theTweet.substring(startIndex, endIndex));
                        saveToDatabase(resolvedUrl);
 
                        Intent tweetMessage = new Intent(TweetTask.NEW_TWEET);
                        tweetMessage.putExtra(android.content.Intent.EXTRA_TEXT, resolvedUrl);
                        sendBroadcast(tweetMessage);
                    }
                }
            }
        };
 
        // code to connect to the twitter streaming API
    }
}

And then the code for BroadcastReceiver becomes much simpler which means we’re doing less work on the UI thread:

private class DataUpdateReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(TweetTask.NEW_TWEET)) {
                String url = intent.getStringExtra(TweetTask.NEW_TWEET);
                updateUI(url);
            }
        }
    }

And the freezing up of the UI is gone!

Reference: Learning Android: Freezing the UI with a BroadcastReceiver from our JCG partner Markh Needham at the Mark Needham Blog.

Related Whitepaper:

Rapid Android Development: Build Rich, Sensor-Based Applications with Processing

Create mobile apps for Android phones and tablets faster and more easily than you ever imagined

Use 'Processing', the free, award-winning, graphics-savvy language and development environment, to work with the touchscreens, hardware sensors, cameras, network transceivers, and other devices and software in the latest Android phones and tablets.

Get it Now!  

Leave a Reply


six − 1 =



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.

Sign up for our Newsletter

20,709 insiders are already enjoying weekly updates and complimentary whitepapers! Join them now to gain exclusive access to the latest news in the Java world, as well as insights about Android, Scala, Groovy and other related technologies.

As an extra bonus, by joining you will get our brand new e-books, published by Java Code Geeks and their JCG partners for your reading pleasure! Enter your info and stay on top of things,

  • Fresh trends
  • Cases and examples
  • Research and insights
  • Two complimentary e-books