Android 防内存泄露的AsyncTask--WeakAsyncTask

来源:互联网 发布:mac air 电池 编辑:程序博客网 时间:2024/04/29 10:06

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, StringMainActivity> {        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 !

点击这里下载源码

0 0
原创粉丝点击