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模型.零拷贝等一些内容, ...
随机推荐
- angular设置全局变量,修改监听变量
创建service.module.ts import { NgModule, ModuleWithProviders } from '@angular/core'; import { SomeShar ...
- systemdump相关
/vendor/sprd/open-source/tools/crashcat sysdump.core.* > dump.bincrash -m phys_base=0x80000000 du ...
- Office Online Server 在线编辑Office文档,安装部署
Office Online Server部署安装 部署环境 一台windows server2012 (搭建域环境)/多次遇坑之后,强烈建议域环境为server2012 一台windows serve ...
- Azure ARM (23) Azure Policy使用
<Windows Azure Platform 系列文章目录> 在之前的文档中,我们介绍了Azure Policy的使用场景. 本章我们介绍如何创建和使用Azure Policy. 模拟场 ...
- (二十三)golang--内置函数
1.用于求长度,占多少个字节 2.内置函数new:分配内存,主要用来分配值类型,比如int.float等,其第一个实参为类型,而非值,其返回值为指向该类型的新分配的零值的指针: 3.make:用来分配 ...
- Python term 模块
Python term 模块 term 模块适用于文字编辑,样式切换,光标移动 等一系列操作适用于终端命令行文字光标处理等操作. 安装 pip install py-term 使用方式 方式一 imp ...
- WPF-数据模板深入(加载XML类型数据)
一.我们知道WPF数据模板是当我们给定一个数据类型,我们为这个数据类型写好布局,就给这种数据类型穿上了外衣. 下面这个例子,能够帮助大家充分理解数据模板就是数据类型的外衣的意思:(里面的MyListB ...
- 基于SqlClient开发SQLServer工具类 伸手党的福音
注意:代码直接Copy调用即可,SQLServer工具类跟我上一个Oracle工具类有所不同,区别在于调用存储过程中时参数的使用,无需输入对应的存储游标名称 特点:根据用户传入的参数类型来识别存储中对 ...
- .NET Core跨平台部署于Docker(Centos)- 视频教程
(双击全屏播放) 往期教程: .NET开发框架(一)-框架介绍与视频演示 .NET开发框架(二)-框架功能简述 .NET开发框架(三)-高可用服务器端设计 .NET开发框架(四)-服务器IIS实践教程 ...
- SQLMap常用教程
先安装 python环境(2.6.x或2.7版本) ,再将SQLMap 放在安装目录下 注意:sqlmap只是用来检测和利用sql注入点的,并不能扫描出网站有哪些漏洞,使用前请先使用扫描工具扫出sql ...