java – AsyncTask and Contexts-ThrowExceptions

Exception or error:

So I’m working out my first multi-threaded application using Android with the AsyncTask class. I’m trying to use it to fire off a Geocoder in a second thread, then update the UI with onPostExecute, but I keep running into an issue with the proper Context.

I kind of hobbled my way through using Contexts on the main thread, but I’m not exactly sure what the Context is or how to use it on background threads, and I haven’t found any good examples on it. Any help? Here is an excerpt of what I’m trying to do:

public class GeoCode extends AsyncTask<GeoThread, Void, GeoThread> {
  @Override
  protected GeoThread doInBackground(GeoThread... i) {
    List<Address> addresses = null;
    Geocoder geoCode = null; 
    geoCode = new Geocoder(null); //Expects at minimum Geocoder(Context context);
    addresses = geoCode.getFromLocation(GoldenHour.lat, GoldenHour.lng, 1);
  }
}

It keeps failing at the sixth line there, because of the improper Context.

How to solve:

@Eugene van der Merwe

The following piece of code works for me : ) –>

public class ApplicationLauncher extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.applicationlauncher);

    LoadApplication loadApplication = new LoadApplication(this);
    loadApplication.execute(null);
}

private class LoadApplication extends AsyncTask {

    Context context;
    ProgressDialog waitSpinner;
    ConfigurationContainer configuration = ConfigurationContainer.getInstance();

    public LoadApplication(Context context) {
        this.context = context;
        waitSpinner = new ProgressDialog(this.context);
    }

    @Override
    protected Object doInBackground(Object... args) {
        publishProgress(null);
        //Parsing some stuff - not relevant
        configuration.initialize(context);
        return null;
    }

    @Override
    protected void onProgressUpdate(Object... values) {
        super.onProgressUpdate(values);
        // Only purpose of this method is to show our wait spinner, we dont
        // (and can't) show detailed progress updates
        waitSpinner = ProgressDialog.show(context, "Please Wait ...", "Initializing the application ...", true);
    }

    @Override
    protected void onPostExecute(Object result) {
        super.onPostExecute(result);
        waitSpinner.cancel();
    }
}
}

Cheers,

Ready4Android

###

The Context is an object which provides accees to application runtime environment. In most cases when you need to obtain objects from Android environment, such as resources, views, infrastructure classes etc — you need to have Context in your hands.

To obtain Context instance is very simple when you’re in the Activity class — Activity itself is a subclass of the Context, so all you need to do — is to use ‘this’ keyword to point on your current context.

Whever you create code which might require Context – you should take care to pass Context object from your parent Activity. In case of your example you could add explicit constructor which accepts Context as input argument.

###

I did some more research, and someone suggested passing it to the thread (not sure why I didn’t think of that). I passed it to the Geocoder thread through an argument, and just like that, it worked.

###

The problem with updating the UI from an AsyncTask is that you need the current activity context. But the context is destroyed and recreated for every orientation change.

Here’s a good answer to your question: Android AsyncTask context behavior

###

If doesn’t look like you are using the params. You could use that to pass in the Conetxt.

public class GeoCode extends AsyncTask<Context, Void, GeoThread> {
  @Override
  protected GeoThread doInBackground(Context... params) {
    List<Address> addresses = null;
    Geocoder geoCode = null; 
    geoCode = new Geocoder(params[0]); //Expects at minimum Geocoder(Context context);
    addresses = geoCode.getFromLocation(GoldenHour.lat, GoldenHour.lng, 1);
  }
}

Then from within your activity:

GeoCode myGeoCode = new GeoCode();
myGeoCode.execute(this);

Leave a Reply

Your email address will not be published. Required fields are marked *