Paul C. Williams

Interfacing Technology & Business
View Paul Williams's profile on LinkedIn
StackOverflow
 3.3k 

Friday, December 13, 2013

Android network development: network activity on main thread?

If you, like me, are learning Android development, and your Android application requires network access, you might see an error like this when you try to access the network:

E/AndroidRuntime(673): java.lang.RuntimeException: Unable to start activity
ComponentInfo{com.example/com.example.ExampleActivity}: android.os.NetworkOnMainThreadException

It turns out that Android has disallowed network activity on the main thread since version 3.0 (Ice Cream Sandwich) or so. This is done to prevent UI blocking during network activity. The fix is to handle the network activity in the background. This sounds scary, but fortunately the developers added a helper abstract class AsyncTask to ease the process.

And it is easy. Here's an example AsyncTask that uses an existing network utility to look up product details based on a string SKU:

private class GetProductTask extends AsyncTask<String,Integer,Product> {
    private String sku; 
    @Override
    protected void onPostExecute(Product p) {
        try {
            if( p == null) {
                // alert the user that we couldn't find a product for the SKU
            }
        } finally {
            // clear the throbber
        }

    @Override
    protected Product doInBackground(String... params) {
        this.sku = params[0];
        // ProductCatalog.locateBySku() is a network activity
        return ProductCatalog.locateBySku(sku);
    }
}

The generic parameters <String,Integer,Product> are the input type, status type, and output type respectively. That is, in our case, the doInBackground() method accepts Strings and when successful onPostExecute() is passed a Product.

This is called simply as an execute to a new object:

new GetProductTask().execute(sku);

You can choose to set up a throbber to communicate to the user that there is an activity in progress.  I made mine modal so that no other data entry could occur while we wait for the network.  That's a different blog posting.

There is also another method you can override, the onProgressUpdate() routine which would be passed an Integer, but in this case I didn't need it.

No comments:

Post a Comment