Search code examples
androidandroid-activityandroid-asynctaskandroid-contextterminate

Android AsyncTask Context Terminated


When an Activity terminates, e.g. after screen orientation changing, is that possible to change an AsyncTask activity context? Else it will create an error because when the activity terminates AsyncTask's activity context is gone too.

My homework done is the following:

public void onSaveInstanceState(Bundle savedInstanceState) <- doesn't solve
public Object onRetainNonConfigurationInstance()  <- doesn't solve
android:configChanges="keyboardHidden|orientation" 
                     <- solved but doesn't handle well relative layouts

Solution

  • What do you pass on your onRetainNonConfigurationInstance()? What I do is pass an object to it containing the AsyncTask, and then I try to retrieve the value in getLastNonConfigurationInstance().

    EDIT: On second thought, it would depend on what you want to do after a configuration change. If you want to terminate the AsyncTask, and then call cancel() on it. If you want to continue its processing even after an orientation change, then you have to hold on to the task.

    You can do that by saving the Activity in the AsyncTask like this:

    private MyAsyncTask searchTask;
    
    @Override
    public void onCreate(Bundle savedInstance){
     super.onCreate(savedInstance);
    
     if (getLastNonConfigurationInstance()!=null) {
      SavedObject savedObj = (SavedObject)getLastNonConfigurationInstance();
    
      searchTask = savedObj.getAsyncTask();
      searchTask.attach(this);
     } else {
      searchTask = new MyAsyncTask(this);
      searchTask.execute();
     }
    }
    
    @Override
    public Object onRetainNonConfigurationInstance(){
    
     searchTask.detach();
    
     final SavedObject savedObj = new SavedObject();
     savedObj.setAsyncTask(searchTask);
    
        return savedObj;
    }
    
    
    private class MyAsyncTask extends AsyncTask<Void, Void, Void> {
    
     MyActivity parentActivity = null;
    
        MyAsyncTask (MyActivity activity) {
      attach(activity);   
     }
    
     void attach(MyActivity activity) {
      this.parentActivity=activity;
     }
    
     void detach() {
      parentActivity=null;
     }
    
     // Do your thread processing here
    }
    
    
    private class SavedObject {
     private MyAsyncTask asyncTask;
    
     public void setAsyncTask(MyAsyncTask asyncTask){
      this.asyncTask = asyncTask;
     }
    
     public MyAsyncTask getAsyncTask() {
      return asyncTask;
     }
    }