AsyncTask是我在项目中经常会用到的一个类,尤其是在操作数据库的时候,之前也用它写过网络请求框架,这个网络框架在用在viewpager加载数据时总是会出现很奇怪的现象,因为AsyncTask是串行执行(android1.6–2.3版本的AsyncTask是并行执行的),所以之后的网络框架换成了线程池,其实AsyncTask也不适合用来做比较耗时请求网络。
生命周期
AsyncTask会一直执行子线程doInBackground()方法,直到方法执行结束,一旦doInBackground()方法执行完,会根据条件来执行不的操作:
(1) 如果cancel(boolean)调用了,则执行onCancelled(Result)方法
(2) 如果cancel(boolean)没有调用,则执行onPostExecute(Result)方法
AsyncTask的cancel方法需要一个布尔值的参数,参数名为mayInterruptIfRunning,意思是如果正在执行是否可以打断,如果这个值设置为true,表示这个任务可以被打断,否则,正在执行的程序会继续执行直到完成。如果在doInBackground()方法中有一个循环操作,我们应该在循环中使用isCancelled()来判断,如果返回为true,我们应该避免执行后续无用的循环操作。
总之,我们使用AsyncTask,需要确保AsyncTask正确地取消。
上面的内容主要参考了: Android中糟糕的AsyncTask 这篇技术博客, 我记得在任玉刚的《Android开发艺术探索》这本书时候也讲到这一点.
内存泄露
在Activity中创建AsyncTask内部类很方便,如果在Acitvity中使用非静态匿名内部类(我的代码经常会出现),非静态的内部类会持有对外部类的隐式引用. 由于AsyncTask的生命周期可能比Activity长,当Activity销毁时,AsyncTask还在执行,由于AsyncTask持有Activity的引用,会导致Acitivity无法回收,产生内存泄露.
在看android源码 (\apps\Contacts\src\com\android\contacts\util) 的时候,注意到一个google工程师写的工具类WeakAsyncTask,内部用到了WeakReference软引用,这样可以解决内存泄露的问题;
其实给AysncTask加上static,静态的内部类不会持有对外部类的引用,就能够解决问题,只不过这样如果AysncTask的方法用到的成员变量都需要加上static;
下面是WeakAsyncTask的源码:
public abstract class WeakAsyncTask<Params, Progress, Result,WeakTarget> extends
AsyncTask<Params,Progress,Result> {
protected WeakReference<WeakTarget> mTarget;
public WeakAsyncTask(WeakTarget target) {
mTarget = new WeakReference<WeakTarget>(target);
}
@Override
protected final void onPreExecute() {
final WeakTarget target = mTarget.get();
if (target != null) {
this.onPreExecute(target);
}
}
@Override
protected final Result doInBackground(Params... params) {
final WeakTarget target = mTarget.get();
if (target != null) {
return this.doInBackground(target,params);
} else {
return null;
}
}
@Override
protected final void onPostExecute(Result result) {
final WeakTarget target = mTarget.get();
if (target != null) {
this.onPostExecute(target,result);
}
}
protected void onPreExecute(WeakTarget target) {
// No default action
}
protected abstract Result doInBackground(WeakTarget target, Params... params);
protected void onPostExecute(WeakTarget target, Result result) {
// No default action
}
}
很简单,用法也几乎和AsyncTask一样:
private static class MyTask extends WeakAsyncTask<Void, Void, String,MainActivity> {
public MyTask(MainActivity target) {
super(target);
}
@Override
protected String doInBackground(MainActivity target, Void... params) {
//获取context,执行一些操作
Context context = target;
return "Hello Android !!!!!";
}
@Override
protected void onPostExecute(MainActivity target, String s) {
//执行操作
}
}
直接调用执行:
new MyTask(this).execute();
其实还可以根据这个思想写一个WeakHandler !