86

I am trying to get the context in my AsyncTask of the class called Opciones(this class is the only one that call that task) but I don't know how to do it, I saw some code like this:

      protected void onPostExecute(Long result) {

    Toast.makeText(Opciones.this,"Subiendo la foto. ¡Tras ser moderada empezara a ser votada!: ", Toast.LENGTH_LONG).show(); 
}

But it doesn't work for me it says: "No enclosing instance of the type Opciones in scope"

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
D4rWiNS
  • 2,585
  • 5
  • 32
  • 54
  • 4
    Is Opciones an activity? If not, you need to pass a context to that class and then use that in the `AsyncTask` – Torben Kohlmeier Jun 04 '13 at 14:52
  • This looks like an answer https://stackoverflow.com/questions/45653121/passing-context-from-service-to-asynctask-without-leaking-it – Mangesh Dec 09 '17 at 20:49

4 Answers4

181

You need to do following things.

  • when you want to use AsyncTask, extend that in other class say MyCustomTask.
  • in constructor of new class, pass Context

Example

public class MyCustomTask extends AsyncTask<Void, Void, Long> {

    private Context mContext;

    public MyCustomTask (Context context){
         mContext = context;
    }

    //other methods like onPreExecute etc.
    protected void onPostExecute(Long result) {
         Toast.makeText(mContext,"Subiendo la foto. ¡Tras ser moderada empezara a ser votada!: ", Toast.LENGTH_LONG).show(); 
    }
}

And instantiate class by following.

MyCustomTask task = new MyCustomTask(context);
task.execute(..);
Chintan Rathod
  • 25,864
  • 13
  • 83
  • 93
  • 38
    note that would be lot better to use non-nested or static class and hold mContext in a WeakReference to avoid memory leaks – BamsBamx Feb 04 '17 at 21:06
  • 9
    Holding context in nested static class throw memory leak warning – Amir Hossein Ghasemi Sep 07 '17 at 12:30
  • 2
    and also holding non-static class in nested-class cause whole class memory leaks warning! so what should we use context without memory leak!? – Amir Hossein Ghasemi Sep 07 '17 at 12:36
  • 1
    Find a way to solve memory leak, Context should be a WeakReference class. – Amir Hossein Ghasemi Sep 07 '17 at 12:40
  • This won't be nested static class. Its public class and needs to be defined separate then activity. But yes, for safer side, we can use WeakReference. – Chintan Rathod Sep 08 '17 at 05:46
  • @Mangesh, which kind of warning it is stating? And if you notice, this answer was given in 2013 and current is 2017. 4 years of gap may have some changes in OS. Don't you think so? – Chintan Rathod Dec 10 '17 at 10:23
  • @ChintanRathod: This is the warning message: This field leaks a context object less. A static field will leak contexts.Non-static inner classes have an implicit reference to their outer class. If that outer class is for example a Fragment or Activity, then this reference means that the long-running handler/loader/task will hold a reference to the activity which prevents it from getting garbage collected. Similarly, direct field references to activities and fragments from these longer running instances can cause leaks. ViewModel classes should never point to Views or non-application Contexts – Alireza Noorali Dec 19 '17 at 08:50
62

Holding a weak reference to the host Activity will prevent memory leaks.

static class MyTask extends AsyncTask<Void, Void, Void> {
    // Weak references will still allow the Activity to be garbage-collected
    private final WeakReference<Activity> weakActivity;

    MyTask(Activity myActivity) {
      this.weakActivity = new WeakReference<>(myActivity);
    }

    @Override
    public Void doInBackground(Void... params) {
      // do async stuff here
    }

    @Override
    public void onPostExecute(Void result) {
      // Re-acquire a strong reference to the activity, and verify
      // that it still exists and is active.
      Activity activity = weakActivity.get();
      if (activity == null
          || activity.isFinishing()
          || activity.isDestroyed()) {
        // activity is no longer valid, don't do anything!
        return;
      }

      // The activity is still valid, do main-thread stuff here
    }
  }
Panda
  • 6,955
  • 6
  • 40
  • 55
Sai
  • 15,188
  • 20
  • 81
  • 121
  • 1
    What about when we switch between activies ( stopping and resuming asyntask), and then come back , Is the weakreference still active? – D4rWiNS Jul 11 '17 at 12:30
  • 1
    Is there benefit to pass the weakReference to the class instead of passing myActivity? – seekingStillness Aug 20 '18 at 13:41
  • 1
    @seekingStillness Weak references will still allow the Activity to be garbage-collected thus preventing a memory leak. – Sai Dec 17 '18 at 05:56
13

Since only one Activity uses this task then just make it an inner class of that Activity

public class Opciones extends Activity
{
     public void onCreate()
     {
         ...
     }

    public class MyTask extends AsyncTask<>
    {
        ...

         protected void onPostExecute(Long result) {
        Toast.makeText(Opciones.this,"Subiendo la foto. ¡Tras ser moderada empezara a ser votada!: ", Toast.LENGTH_LONG).show(); 
     }
}

Then you have access to member variables of the Activity and its Context

codeMagic
  • 44,549
  • 13
  • 77
  • 93
  • 3
    Lint shows a warning about memory leaks if the AsyncTask class isn't static. – SapuSeven Jul 07 '17 at 09:14
  • @SapuSeven Remember that is *is just a warning*. I personally don't think it should be an issue if used correctly as `AsyncTask` are for short lived operations and often for updating views in an `Activity`. It's often a good idea to cancel them in `onPause()` if they are still running. Maybe I'm wrong but those have always been my thoughts on it. [Here is some more reading on the subject](https://stackoverflow.com/questions/14374682/whats-the-correct-way-to-implement-asynctask-static-or-non-static-nested-class). – codeMagic Jul 07 '17 at 13:25
-7

You can write getApplicationContex(). Or Define global variable.

Activity activity;

And at the onCreate() function

activity = this;

then,

 protected void onPostExecute(Long result) {

    Toast.makeText(activity,"Subiendo la foto. ¡Tras ser moderada empezara a ser votada!: ", Toast.LENGTH_LONG).show(); 
}
Sourabh Kumar Sharma
  • 2,864
  • 3
  • 25
  • 33
yahya.can
  • 1,790
  • 1
  • 11
  • 9