原文网址:http://www.jianshu.com/p/0c6f4b6ed558

上篇《坑爹的AsyncTask之内存泄露》已经简单的探讨过线程使用不当会造成内存泄露的问题,在Activity中如果一个线程超出了Activity的生命周期是极有可能发生内存泄露的,那简单来说我们不让线程的生命周期长于Activity就能从根本上解决这个问题。我们今天探讨的主题就是如何让一个Run起来的线程去stop。

听起来有点不可思议,因为JAVA语言中并没有提供相应的API来停止一个正在运行的线程,再来看看我们Android中的“无忧线程”AsyncTask,源码看下来找到一个cancel()方法,看起来似乎是用来cancel当前线程的,写个demo测试下究竟,结果发现这货根本不靠谱。不可能啊,难道Android会提供不靠谱的API给开发者用嘛,回头再来看看cancel()方法的API说明

* <p>Calling this method will result in {@link #onCancelled(Object)} being
* invoked on the UI thread after {@link #doInBackground(Object[])}
* returns. Calling this method guarantees that {@link #onPostExecute(Object)}
* is never invoked. After invoking this method, you should check the
* value returned by {@link #isCancelled()} periodically from
* {@link #doInBackground(Object[])} to finish the task as early as
* possible.</p >

这段注释大概是说,如果调用cancel()方法,它不会立即执行,只有当doInBackground()方法执行完有返回值之后,会在UI主线程调用cancel(),同时也会间接的调用iscancelled(), 并且返回true ,这个时候就不会再调onPostExecute(),然后在doInBackground()里定期检查iscancelled()方法的返回值,是否被cancel,如果return true,就尽快停止。从这段注释里我们似乎发现cancel()方法本身就不太靠谱,因为它的调用在doInBackground()之后执行,假如我就想在doInBackground()里停止当前线程是不是就没有办法了,不保险加不靠谱,我们通过cancel()方法终止线程的想法显然走不通。

但是这段注释似乎给了我们一些启示,可以通过定期检查返回值的方法来判断是否需要停止当前线程。我们要知道在java中,是没有提供相关API来停止一个正在运行中的线程,而Android的AsyncTask也是一样的。如果必须要停止一个线程,我们可以合理利用Java中的Exception,让这个线程在检查到自己需要被停止的时候抛出异常,然后线程就不会再继续执行了,那怎么操作呢,我们可以在这个线程中的耗时操作中设置一些flag,也就是AsyncTask的doInBackground方法中的某些关键步骤。然后在外层需要终止此线程的地方改变这个flag值,线程中的耗时代码一步步执行,当某一时刻发现flag的值变了,throwException,线程就不会再继续执行了。为了保险起见,在外层我们还要捕获这个异常,进行相应处理。

看到这里你是否对这个粗暴的暂停办法留有疑问呢?这样做安全吗,如此粗暴的直接打断AsyncTask真的好么?关于安全问题,如果是在主线程上发生有未处理的异常,将直接导致整个进程终止,简单说就是要用程序fc。但是我们是在AsyncTask的doInBackground方法中打断线程的,doInBackground方法是子线程,子线程被发生异常后会自己死掉而不会引起其他问题,更不会影响到主线程,更何况我们为了更加安全还捕获了异常并做处理,所以这个办法还是安全的,亲测有效。

我们找到了停止Running线程的办法,那么下次只要在Activity生命周期结束之前也结束掉线程的生命,就可以让你的应用程序更加安全健壮了。

如有刊误,欢迎指正。

文/尹star(简书作者)
原文链接:http://www.jianshu.com/p/0c6f4b6ed558
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

【转】坑爹的AsyncTask之根本停不下来的更多相关文章

  1. Android(java)学习笔记149:Android线程形态之 AsyncTask (异步任务)

    1. AsyncTask和Handler的优缺点比较: 1)AsyncTask实现的原理和适用的优缺点        AsyncTask是Android提供的轻量级的异步类,可以直接继承AsyncTa ...

  2. Android(java)学习笔记92:Android线程形态之 AsyncTask (异步任务)

    1. AsyncTask和Handler的优缺点比较: 1)AsyncTask实现的原理和适用的优缺点        AsyncTask是Android提供的轻量级的异步类,可以直接继承AsyncTa ...

  3. Elasticsearch 的坑爹事——记录一次mapping field修改过程

    Elasticsearch 的坑爹事 本文记录一次Elasticsearch mapping field修改过程 团队使用Elasticsearch做日志的分类检索分析服务,使用了类似如下的_mapp ...

  4. app里使用163邮箱发送邮件,被163认为是垃圾邮件的坑爹经历!_ !

    最近有个项目,要发邮件给用户设定的邮箱报警,然后就用了163邮箱,代码是网上借来的^^,如下: package com.smartdoorbell.util; import android.os.As ...

  5. Service和Thread的关系及如何启用Service,如何停用Service

    Service和Thread的关系: 不少Android初学者都可能会有这样的疑惑,Service和Thread到底有什么关系呢?什么时候应该用Service,什么时候又应该用Thread?答案可能会 ...

  6. AsyncTask delay延迟执行 或者顺序执行 问题

    惯用AsyncTask的朋友可能会发现AsyncTask的坑: Android executes AsyncTask tasks before Android 1.6 and again as of ...

  7. Android学习笔记:进度条ProgressBar的使用以及与AsyncTask的配合使用

    ProgressBar时android用于显示进度的组件.当执行一个比较耗时的操作(如io操作.网络操作等),为了避免界面没有变化让用户体验降低,提供一个进度条可以让用户知道程序还在运行. 一.Pro ...

  8. (转)Elasticsearch 的坑爹事——记录一次mapping field修改过程

    Elasticsearch 的坑爹事 本文记录一次Elasticsearch mapping field修改过程 团队使用Elasticsearch做日志的分类检索分析服务,使用了类似如下的_mapp ...

  9. 坑爹的Adprep32.exe

    今天看书的时候,看到用ADSI设置Universal Group Membership Caching,就想到用.Net Framework来实现,找了半天,才找到System.directoryse ...

随机推荐

  1. Android @Field parameters can only be used with form encoding

    今天在学习Retrofit的时候,当post请求时 public interface NewsDataService { @POST("news/list") Call<Ne ...

  2. Azure Service Bus

    Azure Service Bus  是类似Rabbit的一个队列的应用. 找了两个基本的教程 First(但是这个,没有写怎么去链接账户)  Sec:这个有   Third(讲的也很好) Windo ...

  3. 无桌面的linux 安装VMWare Tools

    1.在vmware虚拟机选项下,选择安装vmware-tools 2.将vmware安装目录下的linux.iso装载到系统中 2.1.选择需安装VMWareTools的虚拟机,右击--可移动设备-- ...

  4. js-构造数组

    js中,字符串的特性跟数组非常类似.数组是一种很重要的数据结构.在java中,数组声明的时候就要为其指定类型,数组中只能放同一种类型的数据.Js中的数组可以放不同的类型,但是是有序的,类似于java中 ...

  5. spring IOC bean中注入bean

    俩个实体 package com.java.test4; /** * @author nidegui * @create 2019-06-22 14:45 */ public class People ...

  6. IDEA中使用Database管理工具

    以下内容来自我的知乎回答IntelliJ IDEA中有什么让你相见恨晚的技巧? 说个冷门的,用IDEA操作数据库. 可能大部分不知道,IDEA是自带数据库管理工具的,类似于一个小型Navicat. 具 ...

  7. appium的等待

    在自动化过程中,元素出现受网络环境,设备性能等多种因素影响.因此元素加载的时间可能不一致,从而会导致元素无法定位超时报错,但是实际上元素是正常加载了的,只是出现时间晚一点而已.那么如何解决这个问题呢? ...

  8. S-HR界面控件赋值取值

    属性值: this.getField("entrys.variationReason").shrPromptBox("getValue").name

  9. php curl选项列表(超详细)

    第一类:对于下面的这些option的可选参数,value应该被设置一个bool类型的值:选项可选value值备注 CURLOPT_AUTOREFERER当根据Location:重定向时,自动设置hea ...

  10. 然而,该来的还是来了(Diary)

    2017-05-07     LG月赛成功炸掉...发现自己真的好多东西不会啊.对某些知识仅仅有最基础的一点理解啊!连线段树都理解不了怎么办?归并排序(including分治+贪心)全部炸掉啊.感觉自 ...