【问题标题】:How to force stoping AsyncTask in Android [duplicate]如何在Android中强制停止AsyncTask [重复]
【发布时间】:2014-11-30 17:11:47
【问题描述】:

在我的应用程序中,我有一个 AsyncTask 并且我还创建了一个列表,以将任务添加到该列表中。 在 AsyncTask 我正在下载一些信息,它工作得很好,但是,当使用 finish() 关闭活动时,我经常得到强制关闭,因为 AsyncTask 没有关闭并且当它到达 onPostExecute 并想要与 UI 交互时,它崩溃导致活动已被破坏!

这是我尝试过但没有奏效的方法:

  for (int i = 0; i<tasks.size(); i++){
           tasks.get(i).cancel(true);
       }
  finish();

那么有没有办法强制停止 AsyncTasks ?

【问题讨论】:

  • 使用myAsynTask.cancel(true);
  • 他已经这样做了。而且这个问题不是重复的。

标签: java android android-asynctask android-studio


【解决方案1】:

您对asyncTask.cancel(true) 感兴趣,实际上在其参数中传递了 true,就像在文档中一样:

mayInterruptIfRunning 如果执行此任务的线程应该被中断,则为 true;否则,允许完成正在进行的任务。

然后在您的 AsyncTask.doInBackground 中,您可以进行如下尝试/捕获 - 但这需要您进行引发 InterruptedException 的阻塞调用,否则您需要不时检查 isCancelled():

@Override
protected Void doInBackground(Void... params) {
  try {
    /// do work, 
  } catch (InterruptedException e) {
    if ( isCancelled() ) {
      // cancel(true) called, dont touch UI!
    }
  }
  return null;
}

另外,在onPostExecute() 的开头检查 isCancelled() 是安全的。

当它到达 onPostExecute 并想要与 UI 交互时,它会崩溃

这是另一个问题,如果您在AsyncTask 内部与 GUI 进行交互,我建议首先:使您的 AsyncTask 成为静态类,将对您的 Activity 或 Fragment 的引用传递给 AsyncTask 构造函数,然后将其存储为WeakReference&lt;MyActivity&gt; actRef。然后当你需要它时使用 if ( actRef.get() != null ) { // 使用它。 }。这样,您希望泄漏对您的活动/片段的引用或使用无效的 UI 对象。

【讨论】:

    【解决方案2】:

    尝试创建自己的布尔变量。

    boolean stopNow = false;
    asyncTask.start();
    

    ...异步内部:

    while( ...)
     {
       if( stopNow == true)  finish(); // return();
       ... your main async code
     }
    

    .... 在异步之外(当您需要强制停止异步时,在您的情况下是 Activity.onDestroy() 或 Activity.onPause()):

    stopNow = true; 
    

    【讨论】:

      【解决方案3】:

      您需要告诉您的AsyncTask,它将取消其工作。因此,您需要在您的AsyncTask 实现中定期检查self.isCanceled()。如果结果为true,则您的实现需要停止其工作,否则它将完成整个工作或永远运行,具体取决于实现。

      【讨论】:

        【解决方案4】:

        您应该检查 AsyncTask 的 onPostExecute 中的活动是否为 isDestroyed()。 此外,如果您使用的是内部 AsyncTask 类,则将其设为静态。 使用 Wea​​kReference 来引用你的 Activity 以防止内存泄漏。 (没有办法强制停止 AsyncTask)。

        【讨论】:

        【解决方案5】:

        这里是如何实现这个的例子......

        public class MyTask extends AsyncTask<Void, Void, Void> {
        
        private volatile boolean running = true;
        private final ProgressDialog progressDialog;
        
        public MyTask(Context ctx) {
            progressDialog = gimmeOne(ctx);
        
            progressDialog.setCancelable(true);
            progressDialog.setOnCancelListener(new OnCancelListener() {
                @Override
                public void onCancel(DialogInterface dialog) {
                    // actually could set running = false; right here, but I'll
                    // stick to contract.
                    cancel(true);
                }
            });
        
        }
        
        @Override
        protected void onPreExecute() {
            progressDialog.show();
        }
        
        @Override
        protected void onCancelled() {
            running = false;
        }
        
        @Override
        protected Void doInBackground(Void... params) {
        
            while (running) {
                // does the hard work
            }
            return null;
        }
        
        // ...
        
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-09-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多