[关闭]
@946898963 2020-06-15T17:44:40.000000Z 字数 2045 阅读 976

AsyncTask的cancel方法解读

Android多线程


当我们想要取消AsyncTask方法的运行的时候,我们可以调用cancel()方法来取消运行,但是cancel()方法并不会立即终止AsyncTask的运行,他只会将cancel标志位置位,同时对当前运行doInBackGround方法的线程执行interrupt()方法,也就是说AsyncTask并不会立即终止运行,如果我们想要终止AsyncTask的话,需要在doInBackGround方法中手动的调用isCancelled方法或者Thread.currentThread().isInterrupted()进行判断AsyncTask是否被终止运行。代码如下所示:

  1. @Override
  2. protected Boolean doInBackground(Void... params) {
  3. try {
  4. while (true) {
  5. if(isCancelled())
  6. break;
  7. // if (Thread.currentThread().isInterrupted())
  8. // break;
  9. int downloadPercent = doDownload(); // 这是一个虚构的方法
  10. publishProgress(downloadPercent);
  11. if (downloadPercent >= 100) {
  12. break;
  13. }
  14. }
  15. } catch (Exception e) {
  16. return false;
  17. }
  18. return true;
  19. }

我们可以从源码上对cancel方法进行分析。

AsyncTask的cancel方法的源码如下所示:

  1. public final boolean cancel(boolean mayInterruptIfRunning) {
  2. mCancelled.set(true);
  3. return mFuture.cancel(mayInterruptIfRunning);
  4. }

可以看到cancel方法只是将mCancelled设置位true,同时调用了FutureTask的cancel(boolean mayInterruptIfRunnin)方法,FutureTask的cancel(boolean mayInterruptIfRunnin)方法也只是会对当前正在运行doInBackGround的线程调用interrupt()方法,我们知道线程的interrupt()方法并不会中断线程的运行,而是只会将线程的中断标志位置位,所以AsyncTask的cancel方法并不会取消当前正在运行的AsyncTask。

FutureTask的cancel方法的源码如下所示:

  1. public boolean cancel(boolean mayInterruptIfRunning) {
  2. if (!(state == NEW &&
  3. U.compareAndSwapInt(this, STATE, NEW,
  4. mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
  5. return false;
  6. try { // in case call to interrupt throws exception
  7. if (mayInterruptIfRunning) {
  8. try {
  9. Thread t = runner;
  10. if (t != null)
  11. t.interrupt();
  12. } finally { // final state
  13. U.putOrderedInt(this, STATE, INTERRUPTED);
  14. }
  15. }
  16. } finally {
  17. finishCompletion();
  18. }
  19. return true;
  20. }

从源码可以看出,cancel方法会将cancel标志位置位,同时对当前运行doInBackGround方法的线程执行interrupt()方法,所以如果我们想要在调用过了cancel方法后,让当前正在运行的AsyncTask停止运行,需要在doInBackGround方法中手动的调用isCancelled方法或者Thread.currentThread().isInterrupted()来进行判断,从而做出相应的操作。

当调用cancel方法取消了AsyncTask运行之后,doInBackGround的返回结果,会传递到onCancel方法中,而onPostExecute并不会被调用。这一点从AsyncTaks的finish方法中可以看出:

AsyncTask的finish方法的源码如下所示:

  1. private void finish(Result result) {
  2. if (isCancelled()) {
  3. onCancelled(result);
  4. } else {
  5. onPostExecute(result);
  6. }
  7. mStatus = Status.FINISHED;
  8. }

参考资料:
AsyncTask.cancel()的结束问题
AsyncTask中cancel方法的误读
Android AsyncTask cancel()方法的使用

FutureTask的cancel方法真的能停止掉一个正在执行的异步任务吗

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注