转自:http://blog.csdn.net/snow4dev/article/details/8809897

当AsyncTask被介绍到Android中时,它被贴上“无忧线程”的标签。其目标是让与UI线程交互的后台线程变得更容易。从这一点上讲它是成功的,但并非绝对安全————有很多AsyncTask无法应对的情况。如果不小心处理,不会考虑到AsyncTask出错的情况,很容易盲目使用AsyncTask。下面是一些未充分理解AsyncTask会遇到的问题:

AsyncTask与(屏幕)旋转

AsyncTask的起初目标是为了简化与UI线程进行交互的后台线程的实现。因此多数使用场景是用一个AsyncTask去运行一个耗时的操作,完成之后去更新UI部分(在AsyncTask.onPostExecute()中实现)。

当你旋转屏幕,你会发现这种做法是相当...。当一个App旋转时,整个Activity会被销毁和重建。当Activity重启时,AsyncTask中对该Activity的引用是无效的,因此onPostExecute()就不会起作用。如果使用AsyncTask作为Activity的内部类,AsyncTask会隐式引用了当前Activity,就会出现上述情况,这会使你非常疑惑。

这个问题的通常做法是对AsyncTask持有一个引用,在配置更改,随着Activity重启更新目标Activity。有多种方式可以实现,要么使用一个全局性的持有者(如Application对象),或者通过Activity.onRetainNonConfigurationInstance().传递一个对象。对于基于Fragment的系统,可以使用保留的Fragment(通过Fragment.setRetainedInstance(true)获取)去存储正在运行的AsyncTasks。

AsyncTasks与生命周期

与上面的提到一样:认为生成AsyncTask的Activity终止了,AsyncTask也会终止,这其实是一个误解。它会以它自有的方式继续运行,即使你退出了整个应用程序。AsyncTask提前结束的唯一方法是通过调用AsyncTask.cancel()进行取消。

这表明你必须亲自管理 AsyncTask的取消操作;否则,由于不必要的后台线程会导致app阻塞的风险,或者内存泄露。当不再需要一个AsyncTask时,一定要取消它,防止在app执行期间引起任何问题。

取消AsyncTasks

假设你有一个运行与AsyncTask中的搜索查询。在AsyncTask运行时,用户也许会改变搜索参数,因此你要调用AsyncTask.cancel(),并且为接下来的查询启动一个新的AsyncTask。这似乎合乎逻辑...检查日志后会发现所有的AsyncTask都会完整执行,不论你是否调用了cancel()方法。

传递mayInterruptIfRunning(cancel()方法的参数名)为true都会发生这种情况—————回事?

出现这种情况是因为误解了AsyncTask.cancel()的实际执行效果。AsyncTask不会不考虑结果而直接结束一个线程。调用cancel()其实是给AsyncTask设置一个"canceled"状态。这取决于你去检查AsyncTask是否已经取消,之后决定是否终止你的操作。对于mayInterruptIfRunning——它所作的只是向运行中的线程发出interrupt()调用。在这种情况下,你的线程是不可中断的,也就不会终止该线程。

多数情况下,有两个简单的方法可供选择:在长期运行的操作中定期检查AsyncTask.isCancelled()的调用;或者使线程中断。不论哪种方法,当你调用AsyncTask.cancelled()时,这些方法应该阻止你的操作继续运行。

这个建议并非总是有效————要是调用一个长期运行切不可中断的方法(如 BitmapFactory.decodeStream())会怎么样呢?成功的案例是创建一个引起异常抛出的场景(过早地关闭BitmapFactory使用的流)。这说明cancel()调用并不能解决这个问题————需要外部介入。

在当前AsyncTasks中的限制

我不提倡在后台启动数百个线程;并且,在可启动AsyncTasks的数量上做出限制将毫无用处。最新版的AsyncTask限制使用128个并发线程,另外还有10个在阻塞队列中。因此在队列任务完成之前,如果队列中的task多于138个就会引起app崩溃。使用AsyncTasks从网络加载位图(Bitmap)就会出现这样的问题。

如果想突破这些限制,应该重新思考对后台线程调用的设计。一个可选方案:对tasks设置一个更智能化的队列,这样不必一次性全部启动它们。要是情况紧急,可以拷贝AsyncTask的副本并在代码中调整线程池的大小。

AsyncTask隐藏的陷阱的更多相关文章

  1. C++基于范围循环(range-based for loop)的陷阱

    C++的基于范围的循环是C++11出现的新特性,很方便,一定程度上替代了使用迭代器的for循环用法.不过基于范围的for循环有一个隐藏的陷阱,如果不注意可能会出现严重的内存错误. 举例说明 看下面这个 ...

  2. java生产环境增量发版陷阱【原】

    前言 在生产环境,我们为了降低发版风险,一般都只做增量发布,不做全量发布. 除非项目只有一到两人开发,对时间线和代码脉络结构一清二楚,才可全量发布. 然而增量发布也是有一定隐藏陷阱在里面的,以下就是笔 ...

  3. 深入理解脚本化CSS系列第五篇——动态样式

    前面的话 很多时候,DOM操作比较简单明了,因此用javascript生成那些通常原本是HTML代码生成的内容并不麻烦.但由于浏览器充斥着隐藏的陷阱和不兼容问题,处理DOM中的某些部分时要复杂一些,比 ...

  4. 滴滴与Uber的竞争分析

    滴滴与Uber的竞争分析 随着互联网时代的到来,智能手机的普及,互联网不再是一个完全虚拟的东西,它开始慢慢地融入到我们的生活中来.这些年我们可以明显地感受到我们的生活方式在一天天发生着变化,我们也逐渐 ...

  5. JavaScript 闯关记

    DOM(文档对象模型)是针对 HTML 和 XML 文档的一个 API.DOM 描绘了一个层次化的节点树,允许开发人员添加.移除和修改页面的某一部分. 节点层次 DOM 可以将任何 HTML 或 XM ...

  6. 【JavaScript】【译】编写高性能JavaScript

    英文链接:Writing Fast, Memory-Efficient JavaScript 很多JavaScript引擎,如Google的V8引擎(被Chrome和Node所用),是专门为需要快速执 ...

  7. 编写高性能JavaScript【转】

    英文链接:Writing Fast, Memory-Efficient JavaScript 很多JavaScript引擎,如Google的V8引擎(被Chrome和Node所用),是专门为需要快速执 ...

  8. 《JavaScript 闯关记》之 DOM(下)

    Element 类型 除了 Document 类型之外,Element 类型就要算是 Web 编程中最常用的类型了.Element 类型用于表现 XML 或 HTML 元素,提供了对元素标签名.子节点 ...

  9. NIO相关基础篇三

    转载请注明原创出处,谢谢! 说在前面 上篇NIO相关基础篇二,主要介绍了文件锁.以及比较关键的Selector,本篇继续NIO相关话题内容,主要谈谈一些Linux 网络 I/O模型.零拷贝等一些内容, ...

随机推荐

  1. C++ 模板类示例 template class

    声明和实现在一个文件中: template<class T> class book { public: book(); ~book(); private: }; template<c ...

  2. LeetCode236. 二叉树的最近公共祖先

    * @lc app=leetcode.cn id=236 lang=cpp  *  * [236] 二叉树的最近公共祖先  *  * https://leetcode-cn.com/problems/ ...

  3. 有史以来Mysql面试题大全详解?

    1.MySQL的复制原理以及流程 根柢原理流程,3个线程以及之间的相关: 主:binlog线程——记载下悉数改动了数据库数据的语句,放进master上的binlog中:​ 从:io线程——在运用sta ...

  4. 补充: canal

    1. 作用: 同步mysql:做拉链表:更新redis 某些情况无法从日志中获取信息,而又无法利用sqoop等ETL工具对数据实时的监控 2. canal的工作原理:                 ...

  5. 解决4K屏电脑显示问题

    在科技飞速发展的年代,4K屏幕不断成为电视.电脑广告的亮点功能,它在显示效果上,确实效果不错,如下图.但是,在电脑上使用是否会影响眼睛的健康问题,还没有权威的论证. 毕竟4k高清屏幕还不是主流,很多软 ...

  6. 源码详解系列(五) ------ C3P0的使用和分析(包括JNDI)

    简介 c3p0是用于创建和管理连接,利用"池"的方式复用连接减少资源开销,和其他数据源一样,也具有连接数控制.连接可靠性测试.连接泄露控制.缓存语句等功能.目前,hibernate ...

  7. torch_10_stackGAN-V2

    核心要点 StackGAN旨在生成高分辨率的真实图片. stackGAN-v1架构包含两个阶段:用于文本到图像的合成,阶段1GAN根据给定的文本描述绘制对象的形状和颜色,生成低分辨率图像.阶段2将阶段 ...

  8. 奥展项目笔记05--域名、端口、Nginx相关知识笔记

    1.我国的电信运营商是默认封闭80端口的. 中国电信屏蔽ADSL用户80端口 只是做应用服务器的话你可以使用别的端口. 80端口电脑上同时有各种各样的程序在运行,他们都需要借助网络来进行通信.例如,你 ...

  9. Java8新特性——StreamAPI 的使用

    StreamAPI的说明 Java8中有两大最为重要的改变.第一个是 Lambda 表达式:另外一个则是 Stream API. Stream API ( java.util.stream) 把真正的 ...

  10. MySQL慢日志查询分析方法与工具

    MySQL中的日志包括:错误日志.二进制日志.通用查询日志.慢查询日志等等.这里主要介绍下比较常用的两个功能:通用查询日志和慢查询日志. 1)通用查询日志:记录建立的客户端连接和执行的语句. 2)慢查 ...