Any configuration change will terminate the currently visible Activity and restart it using the new system configuration, so always be prepared for interruptions.
You need to perform tasks asynchronously and want to ensure that a worker thread always sees a valid instance of the Activity that created it, even if that Activity has
been destroyed.
Our idea is as follows: we’ll keep a reference to an Activity in the worker class, but we’ll make sure to reset it whenever that Activity instance changes due to a configuration
the Activity manages the worker instance it’s hosting.the worker manages the activity instace too.
Gracefully managing worker threads across configuration changes:
public class WorkerActivity extends Activity {
private Worker worker;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//check whether a worker object is being passed from a previous instance of this Activity class
worker=(Worker)getLastNonConfigurationInstance();
//if worker is not retained,create new one
if(worker==null){
worker=new Worker();
worker.execute();
}
worker.connectContext(this);//bind current activity
}
@Override
protected void onDestroy() {
super.onDestroy();
worker.disconnectContext();//unbind current activity
}
//pass worker to next activity
@Override
public Object onRetainNonConfigurationInstance() {
return worker;
}
}
Worker implementation that can (dis)connect its hosting Activity:
/*
* keep a reference to an Activity, making sure that its
hosting Activity can bind to the worker B and release itself
*/
public class Worker extends AsyncTask<Void, Void, String> {
private Activity context;
//bind new activity instance
public void connectContext(Activity context) {
this.context = context;
}
//release current activity instance
public void disconnectContext() {
this.context = null;
}
@Override
protected String doInBackground(Void... params) {
// TODO Auto-generated method stub
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
}
return "Work done!";
}
//Only interact with UI if Activity is valid
protected void onPostExecute(String result) {
if (context != null) {
/*
* in cases where our Activity gets destroyed without being recreated,
* as is the case when hitting the back button, or in out-of-memory situations.
*/
Toast.makeText(context, result, Toast.LENGTH_LONG).show();
}
}
}
connect/disconnect pattern.One restriction our solution has is that it only works for activities. The Service class doesn’t define the onRetainNonConfigurationInstance method, so it can’t keep track of task objects it hosts (at least not that way).
Another restriction is that you can’t use the Activity instance in doInBackground because that method doesn’t run on the UI thread, but the task thread, and it’s not
guaranteed that it will always see the correct Activity instance.
If you absolutely can’t live with these restrictions, we have good news as well. The ignition Android application library (http://github.com/kaeppler/ignition) defines an implementation of AsyncTask called IgnitedAsyncTask that allows you to run jobs that are agnostic to the concrete type of their hosting Context, and which make sure
that in all three callback methods you’ll always see the correct context instance.