How to call parent activity function from ASyncTask?

45,126

Solution 1

When you create the AsyncTask, you can add a new constructor to it, and pass in a reference to the Activity:

AsyncTask myTask = new MyTask(this);

And then from the onPostExecute() method in the AsyncTask you can call the method on the Activity.

public class MyTask extends AsyncTask<String, String, String>
{
    public MyActivity activity;

    public MyTask(MyActivity a)
    {
        this.activity = a;
    }

    //  ......

    protected void onPostExecute(String result)
    {
        activity.myMethod();
    }
}

Solution 2

Use Interface

Follow these steps:

1) Create an interface

public interface AsyncTaskListener{

   public void updateResult(String result);

}

2) Use the listener in your AsyncTask

DownloadSongTask extends AsyncTask<String,Integer,String>{

   private AsyncTaskListener listener;

   public DownloadSongTask(Context context)
   {
       listener= (AsyncTaskListener)context;    // Typecast 
   }

   @Override
   public void doInbackGround(String... params)
   {
       // Download code
       int downloadPerc = // calculate that
       publish(downloadPerc);   
   }

   @Override
   public void onPostExecute(String result)
   {
       listener.updateResult(String result);  // Use it 
   }

}

3) Implement the interface in your Activity and Override the interface method

  public class YourActivity extends AppcompatActivity implements AsyncTaskListener{

  // Activity code //
  new  DownloadSongTask(this).execute("Paradise.mp3");  // this is how you start Task

  public void yourMethod(String arg)
  {
    // Your method related Stuff
  }

  @Override 
  public void updateResult(String result){
        yourMethod(result);
  }

}

Advantege of using interface?

This seems a lengthy approach at first but if you use this approach

You can make a loosely coupled AsyncTask. Which means you can use same AsyncTask with any Activity in Future without even changing code in your AsyncTask.

Relevant Links:

For better understanding you can read this ANSWER

Share:
45,126
LA_
Author by

LA_

To search in your posts only type: user:me text To list all your unaccepted questions, type: user:me hasaccepted:0 My questions list: link

Updated on July 09, 2022

Comments

  • LA_
    LA_ almost 2 years

    setAccountAuthenticatorResult can be called from the Activity, which extends AccountAuthenticatorActivity. My activity extends that, but launches ASyncTask and hence this setAccountAuthenticatorResult should be called from ASyncTask (or, the result of ASyncTask should be passed back to the main thread).

    How to do it?

    What is wrong in the code below?

    AsyncTask<Uri, Void, Bundle> task = new RetrieveAccessTokenTask(this, consumer, provider, prefs).execute(uri);
    
    public class RetrieveAccessTokenTask extends AsyncTask<Uri, Void, Bundle> {
        private Context context;
    
        public RetrieveAccessTokenTask(Context context, OAuthConsumer consumer,
                OAuthProvider provider, SharedPreferences prefs) {
            this.context = context;
        }
    
        @Override
        protected void onPostExecute(Bundle result) {
            context.setAccountAuthenticatorResult(); // doesn't work
    
        }
    
  • LA_
    LA_ about 13 years
    Thank, @Ollie C. I've added my approach to the comments. Will it work in the same way as yours? Which approach is better?
  • Ollie C
    Ollie C about 13 years
    I prefer to pass an activity reference rather than the other way around, as it makes more conceptual sense to me, and if I call the task to get the information, how will I know the task is in the right state? Btw, a third option that may be better for some scenarios (e.g. if you needed to update widgets and activities) would be to broadcast an intent, and use broadcast receivers to accept the message.
  • LA_
    LA_ about 13 years
    @Ollie C, in accordance with your approach, I've updated my question with the code - it doesn't work. What is wrong here?
  • Ollie C
    Ollie C about 13 years
    setAccountAuthenticatorResult() is on the Activity class, not the Context class. Your "context" var is the wrong type, use the type of your Activity
  • Ollie C
    Ollie C about 13 years
    In my code sample you'll see I am passing this, but note that this refers to the current activity, so the type of your AsyncTask constructor parameter needs to be Activity, or more specifically your subclass of it (e.g. MyActivity or whatever).
  • LA_
    LA_ about 13 years
    Yes, I got it. But it is not clear for me how to get the current activity to pass it as parameter.
  • Ollie C
    Ollie C about 13 years
    In your activity, the current activity is referenced with this. So pass this to the AsyncTask when you create it. If the Activity class is called MyActivityClass (i.e. MyActivityClass extends Activity) then the type of the param on the constructor needs to be MyActivityClass, and the type of the activity var in the AsyncTask also needs to be like MyActivityClass.
  • wired00
    wired00 almost 12 years
    Hi this is exactly what i am doing ie stackoverflow.com/questions/10843389/… but i worry that calling back to the parent activity will then leave the object containing the Async task ie (MyTask) unable to be garbage collected. Am i completely wrong in that case? Any help really appreciated. Design wise is it generally better to simply keep async code contained with in the "parent" object and not have MyTask at all?
  • Bunny Rabbit
    Bunny Rabbit over 11 years
    you should only use a weak reference to the activity so that it can be garbage collected.
  • Rooster242
    Rooster242 over 10 years
    What's wrong with using this?: MainActivity.this.someParam = whatever;
  • edthethird
    edthethird over 10 years
    This will result in memory leaks, and if your app supports rotation possible null pointers. Do not do this. Instead, do MainActivity.this.someParam or create another subclass to pass between.
  • Joshua Pinter
    Joshua Pinter over 9 years
    Why do you use MyActivity? Wouldn't Activity be correct?
  • Nicolás Carrasco-Stevenson
    Nicolás Carrasco-Stevenson over 8 years
    @JoshPinter Activity is correct, indeed. However if you happen to have your own custom Activity class that extends from Activityyou can use that too. In this example MyActivity is a custom class extending from Activity
  • Joshua Pinter
    Joshua Pinter over 8 years
    @NicolásCarrasco Right on. Thanks for clarifying. That makes sense. Just making sure I wasn't missing anything. ;)