Beginning Android Programming: Acquiring Data
- The Main Thread
- Getting Off the Main Thread
- The AsyncTask
- The IntentService
- Wrapping Up
The Main Thread
The Android operation system has exactly one blessed thread authorized to change anything that will be seen by the user. This alleviates what could be a concurrency nightmare, such as view locations and data changing in one thread while a different one is trying to lay them out onscreen. If only one thread is allowed to touch the user interface, Android can guarantee that nothing vital is changed while it’s measuring views and rendering them to the screen. This has, unfortunately, serious repercussions for how you’ll need to acquire and process data. Let me start with a simple example.
You There, Fetch Me That Data!
Were I to ask you, right now, to download an image and display it to the screen, you’d probably write code that looks a lot like this:
public void onCreate(Bundle extra){ try{ URL url = new url("https://wanderingoak.net/bridge.png"); HttpURLConnection httpCon = (HttpURLConnection)url.openConnection(); if(httpCon.getResponseCode() != 200) { throw new Exception("Failed to connect"); } InputStream is = httpCon.getInputStream(); Bitmap bitmap = BitmapFactory.decodeStream(is); ImageView iv = (ImageView)findViewById(R.id.main_image); iv.setImageBitmap(bitmap); }catch(Exception e){ Log.e("ImageFetching","Didn't work!",e); } }
This is exactly what I did when initially faced with the same problem. While this code will fetch and display the required bitmap, there is a very sinister issue lurking in the code—namely, the code itself is running on the main thread. Why is this a problem? Consider that there can be only one main thread and that the main thread is the only one that can interact with the screen in any capacity. This means that while the example code is waiting for the network to come back with image data, nothing whatsoever can be rendered to the screen.
This image-fetching code will block any action from taking place anywhere on the device. If you hold the main thread hostage, buttons will not be processed, phone calls cannot be answered, and nothing can be drawn to the screen until you release it.
Watchdogs
Given that a simple programmer error (like the one in the example code) could effectively cripple any Android device, Google has gone to great lengths to make sure no single application can control the main thread for any length of time. Starting in Android Honeycomb (3.0), if you open any network connections on the main thread, your application will crash. If you’re hogging too much of the main thread’s time with long-running operations, such as calculating pi or finding the next prime number, your application will produce this disastrous dialog box (Figure 4.1) on top of your application.

Figure 4.1 What the user sees when you hold the main thread hostage.
This dialog box is unaffectionately referred to by developers as an ANR (App Not Responding) crash. Although operations will continue in the background, and the user can press the Wait button to return to whatever’s going on within your application, this is catastrophic for most users, and you should avoid it at all costs.
What Not to Do
What kind of things should you avoid on the main thread?
- Anything involving the network
- Any task requiring a read from or write to the file system
- Heavy processing of any kind (such as image or movie modification)
- Any task that blocks a thread while you wait for something to complete
Excluding this list, there isn’t much left, so as a general rule, if it doesn’t involve setup or modification of the user interface, don’t do it on the main thread.
When Am I on the Main Thread?
Anytime a method is called from the system (unless explicitly otherwise stated), you can be sure you’re on the main thread. Again, as a general rule, if you’re not in a thread created by you, it’s safe to assume you’re probably on the main one, so be careful.