笔记116--AsyncTask问题

来源:互联网 发布:mac移动硬盘不能写入 编辑:程序博客网 时间:2024/05/17 01:49

转自:http://droidyue.com/blog/2014/11/08/bad-smell-of-asynctask-in-android/?droid_refer=ninki_posts

本文介绍AsyncTask会引起哪些问题,如何修复这些问题,并且关于AsyncTask的一些替代方案。

一、生命周期

AsyncTask并不会随着Activity的销毁而销毁。AsyncTask会一直执行doInBackground()直到方法执行结束,一旦上述方法结束,会依据情况进行不同操作。

a.如果cancel(boolean)调用了,则执行onCancel(Result)

b.如果cancel(boolean)没有调用,则执行onPostExecute(Result)

AsyncTask的cancel()需要一个布尔型的参数,参数名为mayInterruptIfRunning,即如果正在执行是否可以打断,如果这个值设置为true,表示这个任务可以被打断,否则,正在执行的程序会执行直到完成。如果在doInBackground()有一个循环操作,我们应该在循环汇总使用isCanceled()来判断,如果返回true,我们应该避免执行后续无用的循环操作。


总之,我们使用AsyncTask需要确保AsyncTask正确的取消。

二、问题
2.1、不好好工作的cancel()

简而言之的答案,有时候起作用。

如果你调用了AsyncTask的cancel(false),doInBackground()仍然会执行到方法结束,只是不会去调用onPostExecute()。但实际上这是让程序执行了没有意义的操作。那么是不是我们调用cancel(true)前面的问题就能解决了呢?并非如此,如果mayInterruptIfRunning设置为true会使任务尽早结束,但是如果doInBackground()有不可打断的方法会失效,比如BitmapFactory.decodeStream()IO操作。但是你可以提前关闭IO流并捕获这样操作抛出的异常。但是这样会使得cancel()没有任何意义。

2.2、内存泄露

另一种常见的情况是,在Activity中使用静态匿名内部类AsyncTask类,由于Java内部类的特定,AsyncTask内部类会外部类的隐式引用。消息参考细话Java:“失效”的private修饰符,由于AsyncTask的生命周期比Activity的长,当Activity执行销毁AsyncTask还在执行时,由于AsyncTask持有Activity的引用,导致Activity对象无法回收,进而产生内存泄露。

2.3、结果丢失

另一个问题是在屏幕旋转等造成Activity重新创建时AsyncTask数据丢失的问题。当Activity销毁并重新创建后,还在运行的AsyncTask会持有一个Activity的非法引用即之前的Activity实例。导致onPostExecute()没有任何作用。

三、替代方案

真的需要AsyncTask么?推荐的一种进行异步操作的技术是使用Loaders。这个方法从Android3.0开始引入,在Android支持包中也有包含。可通过查看官方文档详细了解Loaders。

0 0
原创粉丝点击