AsyncTask隐藏的陷阱
转自: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隐藏的陷阱的更多相关文章
- C++基于范围循环(range-based for loop)的陷阱
C++的基于范围的循环是C++11出现的新特性,很方便,一定程度上替代了使用迭代器的for循环用法.不过基于范围的for循环有一个隐藏的陷阱,如果不注意可能会出现严重的内存错误. 举例说明 看下面这个 ...
- java生产环境增量发版陷阱【原】
前言 在生产环境,我们为了降低发版风险,一般都只做增量发布,不做全量发布. 除非项目只有一到两人开发,对时间线和代码脉络结构一清二楚,才可全量发布. 然而增量发布也是有一定隐藏陷阱在里面的,以下就是笔 ...
- 深入理解脚本化CSS系列第五篇——动态样式
前面的话 很多时候,DOM操作比较简单明了,因此用javascript生成那些通常原本是HTML代码生成的内容并不麻烦.但由于浏览器充斥着隐藏的陷阱和不兼容问题,处理DOM中的某些部分时要复杂一些,比 ...
- 滴滴与Uber的竞争分析
滴滴与Uber的竞争分析 随着互联网时代的到来,智能手机的普及,互联网不再是一个完全虚拟的东西,它开始慢慢地融入到我们的生活中来.这些年我们可以明显地感受到我们的生活方式在一天天发生着变化,我们也逐渐 ...
- JavaScript 闯关记
DOM(文档对象模型)是针对 HTML 和 XML 文档的一个 API.DOM 描绘了一个层次化的节点树,允许开发人员添加.移除和修改页面的某一部分. 节点层次 DOM 可以将任何 HTML 或 XM ...
- 【JavaScript】【译】编写高性能JavaScript
英文链接:Writing Fast, Memory-Efficient JavaScript 很多JavaScript引擎,如Google的V8引擎(被Chrome和Node所用),是专门为需要快速执 ...
- 编写高性能JavaScript【转】
英文链接:Writing Fast, Memory-Efficient JavaScript 很多JavaScript引擎,如Google的V8引擎(被Chrome和Node所用),是专门为需要快速执 ...
- 《JavaScript 闯关记》之 DOM(下)
Element 类型 除了 Document 类型之外,Element 类型就要算是 Web 编程中最常用的类型了.Element 类型用于表现 XML 或 HTML 元素,提供了对元素标签名.子节点 ...
- NIO相关基础篇三
转载请注明原创出处,谢谢! 说在前面 上篇NIO相关基础篇二,主要介绍了文件锁.以及比较关键的Selector,本篇继续NIO相关话题内容,主要谈谈一些Linux 网络 I/O模型.零拷贝等一些内容, ...
随机推荐
- Ubuntu16.04下安装Cmake-3.8.2并为其配置环境变量
下载安装包 首先我们到官网下载最新的cmake二进制安装包https://cmake.org/files/ 这里,我下载的是比较新的cmake-3.8.2-Linux-x86_64.tar.gz解压安 ...
- Apache 监听 ipv4
查看端口信息 ifconfig 发现只有 ipv6 的 80 端口被监听,ipv4 的 80 端口没有被监听 因此通过 ipv4 无法访问 tcp6 0 0 :::80 :::* LISTEN 221 ...
- ESA2GJK1DH1K升级篇: 阿里云物联网平台 OTA: 关于阿里云物联网平台 OTA 的升级流程
前言 鉴于有些用户直接想使用现成的物联网平台实现 OTA 远程升级 我就写一写这系列的文章 注意:首先大家必须把我自建服务器是如何实现的看明白! 我看了下阿里云提供的,实际上流程和咱自建实现的差别不大 ...
- C 函数与指针(function & pointer)
C 函数与指针(function & pointer) /* * function.c * 函数在C中的使用 * */ #include <stdio.h> int noswap( ...
- python 机器学习基础教程——第一章,引言
https://www.cnblogs.com/HolyShine/p/10819831.html # from sklearn.datasets import load_iris import nu ...
- 解决node fs.writeFile 生成csv 文件乱码问题
解决node fs.writeFile 生成csv 文件乱码问题: fs.writeFile('xxx.csv', '\ufeff' + 要传入的数据, {encoding: 'utf8'}); \u ...
- H5 背景图片自适应屏幕问题解决办法
今天也是偶然遇到这个问题的,平成很少用到关于css的内容,就在网上找了很多个方法,最后总结以下几种很实用的方法 方法1: <style> body{ background:url(beij ...
- 计算机基础 ---- 编码(er)
1.字符集与编码 字符集:字符组成的集合,汉字,字母,符号被收录到标准的字符集合 编码:规定每个字符使用一个字节还是多个字节存储,那些字节来存储的规定 术语:字符编码(character encodi ...
- Vue.js 源码分析(十五) 指令篇 v-bind指令详解
指令是Vue.js模板中最常用的一项功能,它带有前缀v-,比如上面说的v-if.v-html.v-pre等.指令的主要职责就是当其表达式的值改变时,相应的将某些行为应用到DOM上,先介绍v-bind指 ...
- Linux 搭建邮件服务器
一.概述: 在配置邮件服务器之前,先解释几个概念. 1.SMTP:简单邮件传输协议 (Simple Mail Transfer Protocol, SMTP) 通常使用Email都很容易,但是Inte ...