Android之AsyncTask异步任务——防止内存泄露

Android的异步任务有很多实现方法,最常见的如Handler、Thread、AsyncTask;还有一些开源项目也可以做到异步任务和线程间通信等功能,例如:EventBus、RxAndroid等,我们这里就不讨论用哪种实现方式更好,只是根据实际需求进行合适的筛选。

笔者公司的项目算是大型的互联网金融类的App,由于历史架构原因未用到一些新的开源项目,也不能盲目引入这些开源的项目,所以只能在Handler、Thread、AsyncTask中选择一个进行封装了。封装要求:调用便捷、灵活、可扩展,最重要是防止内存泄露,最好能在调用者销毁时自动中断并释放所有异步任务资源。

Handler已经不能再熟悉了,封装起来虽然更能得心应手,但是考虑时间问题觉得AsyncTask更简单,因为google已经对异步任务进行了封装,所以才有了AsyncTask这个类。但要注意的是AsyncTask是顺序执行的,也就是并不适合并发需求,如有并发需求请跳过。

整个封装简单,直接上工具类代码:


package asyncTask;


import android.util.Log;

import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 异步任务工具类
 * 支持任务的执行与Activity生命周期进行绑定
 */
public class AsyncTaskUtil {

    private static Map>> taskMap = new ConcurrentHashMap<>();

    /**
     * 异步任务
     * @param obj 请求标识
     * @param call 回调
     * @param params 入参
     */
    public static  void doAsync(Object obj, AsyncCall call, Object... params){
        MyAsyncTask task = new MyAsyncTask() {
            @Override
            protected T doInBackground(Object... params) {
                try {
                    return call.onCall(params);
                } catch (Exception e){
                }
                return null;
            }

            @Override
            protected void onProgressUpdate(Integer... values) {
                call.onProgressUpdate(values);
            }

            @Override
            protected void onPreExecute() {
                call.onPreCall();
            }

            @Override
            protected void onPostExecute(T t) {
                call.onCallFinished(t);
                call.cancel(true);
                destroyTask(obj, this);
            }


        };
        call.bindTask(task);
        addTask(obj, task);
        task.execute(params);

    }

    /**
     * 异步任务
     * @param obj 请求标识
     * @param call 回调
     * @param params 入参
     */
    public static void doAsync(Object obj, AsyncCallSimple call, Object... params){
        MyAsyncTask task = new MyAsyncTask(){
            @Override
            protected Object doInBackground(Object[] params) {
                try {
                    return call.onCall(params);
                } catch (Exception e){
                }
                return null;
            }

            @Override
            protected void onPostExecute(Object o) {
                call.onCallFinished(o);
                call.cancel(true);
                destroyTask(obj, this);
            }

            @Override
            protected void onPreExecute() {
                call.onPreCall();
            }

            @Override
            protected void onProgressUpdate(Object[] values) {
                call.onProgressUpdate(values);
            }
        };
        call.bindTask(task);
        addTask(obj, task);
        task.execute(params);

    }

    /**
     * 销毁(释放资源并防止多线程在页面销毁时操作UI):请在Activity的onDestroy方法中调用
     * @param obj 请求标识
     */
    public static void destroy(Object obj){
        final String tag = obj.getClass().getName();
        HashMap> map = taskMap.get(tag);
        if(null != map){
            for(Map.Entry> entry : map.entrySet()){
                if(null != entry.getValue().get()){
                    MyAsyncTask task = entry.getValue().get();
                    showLog("destroy["+tag+"] task="+ task.hashCode());
                    task.cancel(true);
                }
            }
            taskMap.remove(tag);
        }
    }

    private static void addTask(Object obj, MyAsyncTask task){
        final String tag = obj.getClass().getName();
        HashMap> map = taskMap.get(tag);
        if(null == map){
            map = new HashMap>();
            map.put(task.hashCode(),new WeakReference(task));
            taskMap.put(tag, map);
        }else{
            map.put(task.hashCode(),new WeakReference(task));
        }
        showLog("add["+tag+"] task="+ task.hashCode());
    }

    private static void destroyTask(Object obj, MyAsyncTask task){
        final String tag = obj.getClass().getName();
        HashMap> map = taskMap.get(tag);
        if(null != map){
            WeakReference wTask = map.get(task.hashCode());
            if(null != wTask){
                MyAsyncTask myTask = wTask.get();
                showLog("destroy["+tag+"] task="+ myTask.hashCode());
                map.remove(myTask);
                taskMap.put(tag,map);
                myTask.cancel(true);
            }
            if(map.size() == 0){
                taskMap.remove(tag);
            }
        }
    }

    private static void showLog(String msg){
        Log.d("AsyncTaskUtil",msg);
    }


}

工具类中使用了两个抽象类:

异步任务回调抽象类

package asyncTask;



public abstract class AsyncCallAbs {

    //UI线程执行:在onCall之前执行
    abstract void onPreCall();

    //非UI线程执行:执行耗时操作
    abstract T onCall(Object[] objects) throws Exception;

    //非UI线程执行:用于通知进度更新
    abstract void publishProgress(Integer... values);

    //UI线程执行:更新进度
    abstract void onProgressUpdate(Integer[] values);

    //UI线程执行:异步任务执行完毕
    abstract void onCallFinished(T result);

    abstract void cancel(boolean mayInterruptIfRunning);

}


异步任务回调类


package asyncTask;

//Object 启动任务执行的输入参数。
//Integer 后台任务执行的百分比。
//T 后台执行任务最终返回的结果,比如String。
public class AsyncCall extends AsyncCallAbs {

    private MyAsyncTask task;

    public void bindTask(MyAsyncTask task){
        this.task = task;
    }


    @Override
    public T onCall(Object[] objects) throws Exception {
        return null;
    }

    @Override
    public void onCallFinished(T result) {
    }

    @Override
    public void onPreCall() {

    }

    @Override
    public void onProgressUpdate(Integer[] values) {

    }

    @Override
    public void publishProgress(Integer... values) {
        if(null != task)
            task.publishProgress(values);
    }

    @Override
    public void cancel(boolean mayInterruptIfRunning) {
        if(null != task){
            task = null;
        }
    }



}

Activity中调用方法

AsyncTaskUtil.doAsync(this,new AsyncCall(){
                    @Override
                    public String onCall(Object[] obj) throws Exception {
                        for(int i=0;i<10;i++){
                            publishProgress(i);
                            Thread.sleep(200);
                        }
                        return obj[0].toString()+" "+obj[1].toString();
                    }

                    @Override
                    public void onCallFinished(String result) {
                        tv.setText(result);
                    }

                    @Override
                    public void onProgressUpdate(Integer[] values) {
                        tv.setText(values[0].toString());

                    }
                },"hello","world");

该方法调用时会每0.2秒刷新一下TextView,请在Activity的onDestroy方法中增加销毁异步任务方法的调用(也可以自己监听Activity生命周期进行销毁操作):

@Override
    protected void onDestroy() {
        AsyncTaskUtil.destroy(this);
        super.onDestroy();
    }

下面提供了一个异步任务的简单回调类:

package asyncTask;


public class AsyncCallSimple extends AsyncCallAbs {

    private MyAsyncTask task;

    public void bindTask(MyAsyncTask task){
        this.task = task;
    }

    @Override
    public void onPreCall() {

    }

    @Override
    public Object onCall(Object[] objects) throws Exception {
        return null;
    }

    @Override
    public void publishProgress(Object... values) {
        if(null != task)
            task.publishProgress(values);
    }

    @Override
    public void onProgressUpdate(Object[] values) {

    }

    @Override
    public void onCallFinished(Object result) {
    }

    @Override
    public void cancel(boolean mayInterruptIfRunning) {
        if(null != task){
            task = null;
        }
    }
}

最后说一下MyAsyncTask类,该类只是对原生的AsyncTask类所以一点修改,将publishProgress方法的private改成public。

 public final void publishProgress(Progress... values) {
        if (!isCancelled()) {
            getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
                    new AsyncTaskResult(this, values)).sendToTarget();
        }
    }




你可能感兴趣的:(Android)