在AsyncTask中获取上下文信息

86
我正在尝试在名为Opciones的类的AsyncTask中获取上下文(该类是唯一调用该任务的类),但我不知道如何实现,我看到了一些类似于这样的代码:
      protected void onPostExecute(Long result) {

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

但是对我不起作用,它显示:"No enclosing instance of the type Opciones in scope"


4
Opciones是一种活动吗?如果不是,你需要向那个类传递一个上下文,然后在AsyncTask中使用它。 - Torben Kohlmeier
这看起来像是一个答案 https://dev59.com/iFcO5IYBdhLWcg3wiyGU - Mangesh
4个回答

182

你需要做以下几件事情:

  • 当你想要使用AsyncTask时,可以在其他类中扩展它,比如MyCustomTask
  • 在新类的构造函数中传递Context

示例:

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(); 
    }
}

按照以下方式实例化类。

MyCustomTask task = new MyCustomTask(context);
task.execute(..);

38
请注意,最好使用非嵌套或静态类,并将mContext保存在WeakReference中,以避免内存泄漏。 - BamsBamx
9
嵌套的静态类持有上下文会引发内存泄漏警告。 - Amir Hossein Ghasemi
2
同时,在嵌套类中持有非静态类会导致整个类的内存泄漏警告!那么我们应该如何使用上下文而不会出现内存泄漏呢? - Amir Hossein Ghasemi
1
寻找解决内存泄漏的方法,上下文应该是一个WeakReference类。 - Amir Hossein Ghasemi
@Mangesh,它是在警告什么?如果你注意到,这个答案是在2013年给出的,而现在是2017年。4年的时间可能会对操作系统产生一些变化。你不觉得吗? - Chintan Rathod
显示剩余2条评论

62
持有对宿主Activity的弱引用将防止内存泄漏。
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
    }
  }

1
当我们在活动之间切换(停止和恢复asyntask),然后回来时,弱引用仍然有效吗? - D4rWiNS
1
将weakReference传递给类,而不是传递myActivity,是否有好处? - seekingStillness
1
@seekingStillness 弱引用仍然允许Activity被垃圾回收,从而防止内存泄漏。 - Sai

13

由于只有一个 Activity 使用此任务,因此将其设置为该 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(); 
     }
}

那么您就可以访问Activity和它的Context成员变量。


3
如果AsyncTask类不是静态的,Lint会显示有关内存泄漏的警告。 - SapuSeven
@SapuSeven 记住这只是一个警告。我个人认为,如果正确使用,它不应该成为问题,因为 AsyncTask 用于短暂的操作,通常用于在 Activity 中更新视图。如果它们仍在运行,最好在 onPause() 中取消它们。也许我错了,但这一直是我的想法。这里有更多关于此主题的阅读材料 - codeMagic

-7

你可以写getApplicationContex()。或者 定义全局变量。

Activity activity;

而在 onCreate() 函数中

activity = this;

然后,

 protected void onPostExecute(Long result) {

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接