【问题标题】:Activity is destroyed but asynctask is still runningActivity 被销毁但 asynctask 仍在运行
【发布时间】:2015-04-18 18:32:49
【问题描述】:

我正在处理推送通知。问题是当我加载一个非常大的表单并且我收到通知时,在表单完全加载之前我尝试点击通知我在 5-6 秒后得到一个空白屏幕。异常是由于 dialog.dismiss。

据我了解,在打开通知时,当前活动被销毁,一个新活动被创建。在创建新活动时,我正在使用 asynctask 在我的应用程序中完成一些其他功能。因此,当当前活动被销毁时,活动上下文为空,但 asynctask 仍在运行,同时还有进度对话框。一旦活动被破坏,就没有窗口显示对话框,因此窗口泄漏异常。

任何人都可以帮助我摆脱这个问题。当应用程序空闲很长时间然后我打开通知时,我也会得到空白屏幕。

有没有办法在活动被销毁后立即停止运行异步任务。

我的代码是:

公共类 MainActivity 扩展 Activity {

  private MyProgressDialog myProgressDialog;  
  public  LinearLayout mainPanel;  
  private VMobilet mobilet = null;  
  private String mobiletId;  
  private String formId ;

  @Override  
protected void onCreate(Bundle icicle) {  
    super.onCreate(icicle);   
    setContentView(mainPanel);   

    Intent i = getIntent();  
    mobiletId = i.getStringExtra("Mobilet Id");  
    formId = i.getStringExtra("Form ID");  
            VUiHelper.getInstance().setIsFinish(false);  
    myProgressDialog = MyProgressDialog.show(MainActivity.this,"","",true);  

    BackgroundTask backgroundTask = new BackgroundTask();  
    backgroundTask.execute(MainActivity.this);  
}  

    @Override  
protected void onPause() {  
    super.onPause();  
    if(VUiHelper.getInstance().isFinish())  
        {         
            this.finish();    
        }       
    else {  
         System.out.println("pausing mainactivity");  
    }  
}  

    @Override  
protected void onDestroy() {  
    super.onDestroy();  
    System.out.println("mainactivity ondestroy called");  
    if(mobilet != null)  
    mobilet.getForms().clear();  
    mobilet = null;  
    mainPanel = null;  
    VUiHelper.getInstance().clearControlCache();  
    VUiHelper.getInstance().MediaInput.clear();  
    System.gc();  
}  

    private class BackgroundTask extends AsyncTask<Context, String, Boolean> {  

    @Override  
    public void onPreExecute() {    
        super.onPreExecute();   
    }  

    @Override  
    protected Boolean doInBackground(Context... arg0) {  
        if (mobiletId != null) {  
            ** some logic **  
        }  
        return true;  
    }  

    @Override  
    public void onPostExecute(Boolean status){              
         super.onPostExecute(status);          
         myProgressDialog.dismiss();  //dismissing the progress dialogs    
         if (mobilet != null) {  
                      ** some logic  **  
         } else {  
              ** some logic **  
                 }  
     }  
     }      
}  
 }  

我尝试在 onDestroy() 中打印活动上下文,结果为空。

【问题讨论】:

  • 另外我想恢复 asynctask 的实例并将其传递给要创建的新活动。

标签: android


【解决方案1】:

您可以停止运行 Asynctask(只要您有对其的引用)。你可能想做这样的事情

开始时:

Task ref = new Task();
ref.execute()

然后在 onPause() 中

if(ref != null)
     ref.cancel(true);

如果你定期做某事(比如下载),那么在你的 doInBackground() 里面有这样的东西:

if(isCanceled())
{
    return;
}

上面的 sn-ps 应该可以让你优雅地退出异步任务。

也在你的 onPause 中

if(myProgressDialog != null)
{
    if(myProgressDialog.isShowing())
    {
         myProgressDialog.dismiss()
    }
    myProgressDialog = null
}

然后在你的 onPostExecute 中

if(myProgressDialog != null)
{
    if(myProgressDialog.isShowing())
    {
        myProgessDialog.dismiss;
        myProgessDialog = null;
    }
}

在 onPuase 中将 myProgessDialog 设置为 null 应该使其在 onPOstExecute() 中为 null

【讨论】:

  • 你说的是直到在后台运行。如果你在任务上设置了 cancel(true),那么一旦它完成 doInBackground 并返回它就不应该调用 onPostExecute()。还发布了一条 Log 语句,表示正在调用 onPostExecute。因为它不应该发生。
【解决方案2】:

您可以通过调用 cancel(Boolean) 来取消 AsyncTask。有关该页面上“取消任务”的更多使用信息,请按 ctrl-f

【讨论】:

  • “尝试取消此任务的执行。”异步任务是低优先级线程。并且线程不能在 java 中可靠地杀死。
  • 是的。这就是为什么如果您需要尽快退出,文档建议在后台方法中定期检查 isCancelled()
  • 请注意,如果您在 AsyncTask 上调用 cancel(true),则 AsyncTask 后台线程中的大多数阻塞 I/O 调用将被中断。
【解决方案3】:

我认为解决该问题的最佳方法是让您的 asyntask 检查是否仍有应用程序在运行。如果不是简单地退出。在 Activity.onPause 中设置一个标志,让异步任务在发送一些输出之前检查它。

【讨论】:

    最近更新 更多