Android 防内存泄露的AsyncTask--WeakAsyncTask

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
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值