Android AsynchTask在其调用活动完成时工作

Android AsynchTask在其调用活动完成时工作,android,android-asynctask,Android,Android Asynctask,当AsynchTask位于doinBackground()方法中时,我的活动已完成 当它到达postExecute()时,用于更新UI的活动已被销毁,但其TextView仍可以在onPostExecute()中访问 有人能解释一下这是怎么发生的吗?在启动新活动之前,在异步任务上调用cancel asynTask.cancel(true) 在asynctasksdoInBackground方法中,检查是否取消了AsyncTask @Override protected String doInBa

AsynchTask
位于
doinBackground()
方法中时,我的活动已完成

当它到达
postExecute()
时,用于更新UI的活动已被销毁,但其
TextView
仍可以在
onPostExecute()
中访问

有人能解释一下这是怎么发生的吗?

在启动新活动之前,在
异步任务上调用cancel

asynTask.cancel(true)
在asynctasks
doInBackground
方法中,检查是否取消了
AsyncTask

@Override
protected String doInBackground(String... urls) {
   for( !isCancelled()) { 
      //do some stuff
  }
}

Android活动有一个特定的生命周期。当它们超过销毁生命周期状态时,Android将不再使用它们,最终将被垃圾收集

但是,当您将活动引用或任何小部件引用传递给AsyncTask时,这会阻止GC处理活动及其相关对象(例如视图和小部件)。此外,AsyncTask在单独的线程中以自己的状态执行,它将包含一个或多个无效对象的引用。由于您在AsyncTask中持有引用,GC无法释放它们


这就是为什么在使用带有活动引用的异步任务时必须非常小心的原因。另外,不要使用AsyncTasks更新UI,还有其他方法可以做到这一点。

这个问题需要解释它是如何发生的。 想想这个简单的java代码

public class myClass{
   public static void main(String[] args) {
     int n=2;
     MyThread t=new MyThread(n);
     t.start();
     n=4;
     System.out.println("n from main "+n);
   }
}

class MyThread extends Thread{
    int n;
    public MyThread(int n){
        this.n=n;
    }

    @Override
    public void run(){
        try{
            Thread.sleep(2000);
        }catch(Throwable e){
            System.out.println("error :"+e);
        }
        System.out.println("n from thread "+n);
    }
}
而输出将是,

n from main 4
n from thread 2

发生这种情况是因为传递给线程的整数n的实例保留其值。这与异步任务中发生的情况相同。如果将n设为静态变量并在新线程中对其进行引用,则此行为将发生更改

您的
活动
可能会因为以下几个原因而被破坏:

  • 由于内存需要,系统正在清除您的
    活动
  • 你转动手机。然后,
    活动
    被终止并重新创建
  • 您可以显式地从
    活动返回
在执行
异步任务时,您的逻辑需要处理此类场景。一旦您的
活动
启动了一个
异步任务
,它将在另一个线程中执行,并在完成后将结果返回给您的
活动
。您的
活动
可能会在后台
异步任务
执行工作时被终止。一个好的做法是,一旦您的
活动
被终止(onDestroy),并且如果您不希望继续执行
异步任务

异步任务(与标准java线程相同)的结果,则调用
取消(布尔)
方法不考虑主机活动的生命周期。由开发人员来实现适当的取消(如@mrDroid所示)

您可以使用AsyncTaskLoader,因此不必编写处理活动配置更改的代码


请注意,即使没有直接引用主机活动(如@George Metaxas所述),非静态内部异步任务也可能导致内存泄漏(因为内部类包含对外部类的隐式引用)。

当您完成活动时,您也应该取消
异步任务(如果它仍在运行)。请看这里。