原文网址: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. C# 怎么把类文件如(XXX.cs)转为dll文件

    打开VS2012或2017 ,新建项目,选择  类库(.NET Framework),创建好一个项目 在建好的项目中添加需要转的类文件 然后将项目重新生成后,在项目的Debug下就可以找到对应的dll ...

  2. 自动换行 word-break:break-all和word-wrap:break-word

    1.word-break:break-all;当内容(比如很长的一个单词)到每行的末端时,它会把单词截断显示一部分,下一行显示后一部分. 2.word-wrap:break-word;当内容(比如很长 ...

  3. Excel的用到的常规的技巧

    这几天在做各种发票的报表,好几百的数据当然离不开EXCel,自己又是个白班,就记录下啦! EXCEL 判断某一单元格值是否包含在某一列中 就在Excel的表格中加入这个函数:=IF(ISERROR(V ...

  4. DataGridView 单击赋值

    void dataGridView1_Click(object sender, EventArgs e) { M_int_judge = ; btnSave.Enabled = true; btnSa ...

  5. luogu P4719 【模板】动态 DP 矩阵乘法 + LCT

    方法二:LCT+矩阵乘法 上文中,我们用线段树来维护重链上的各种矩阵转移. 第二种方法是将树链剖分替换为动态树. 我们知道,矩阵乘法 $\begin{bmatrix} F_{u,0} & F_ ...

  6. PAT_A1150#Travelling Salesman Problem

    Source: PAT A1150 Travelling Salesman Problem (25 分) Description: The "travelling salesman prob ...

  7. python 从Excel中取值

    import openpyxl from openpyxl import load_workbook def open_file(file_path): workbook = load_workboo ...

  8. QBXT Day2

    遭遇[问题描述]你是能看到第一题的 friends呢.—— hjaN座楼房,立于城中 .第i座楼,高度 hi.你需要一开始选择座楼,开始跳楼. 在第 i座楼准备跳需要 ci的花费. 每次可以跳到任何一 ...

  9. SpringBoot 读取配置文件的值 赋给静态变量

    需求:写了一个工具类,但是工具类中的一些变量需要放到配置文件中,而这个工具类中的变量与方法都是静态的,这个时候我需要一个办法将配置文件中的相关配置读取过来赋值给这些静态变量.找了一些文章,试了一些方法 ...

  10. wordpress常见问题

    一.WordPress新手必须注意的两个设置 第一 :设置里面的媒体--关闭wordpress缩略图功能如果开启了三种缩略图,博客上传的图片就会生成不同大小的三份,而基本上博客又没有使用,这样下来严重 ...