自己实现轻量级的AsyncTask

728 阅读3分钟

说在前面

用过AsyncTask的都知道,AsyncTask是为了在异步线程执行耗时任务以免阻塞UI线程而设计的。但是在使用过程中发现它存在一些缺点:

  1. 个人感觉AsyncTask学习成本有点高,因为它带三个泛型参数,学习成本略微有点高;
  2. AsyncTask在Activity中使用不注意容易造成内存泄露,因为AsyncTask时常被用作Activity的内部类来使用,有时由于某些原因造成异步任务的执行时间长达几十秒甚至更长,当页面关闭时,异步任务没结束并对Activity持有引用,Activity不能被及时回收,导致内存泄露。
  3. AsyncTask未绑定生命周期,并不能自行根据生命周期结束异步任务,只能人为结束任务。

由于AsyncTask存在这些缺点,所以想自己实现一个轻量级的AsyncTask。

AsyncTask如何实现呢

第一,要能执行异步任务,首先内部实现要能开启新线程去执行,然后要能多任务并发,且并发线程数不宜过多,所以想到用线程池,采用固定数目线程数的线程池,并发线程数控制为多少呢,当然是设置为CPU核的数目比较适宜。

private ExecutorService threadPool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

第二,异步任务执行完之后要能切回UI线程执行,所以要用UI线程的Handler。

private Handler mainHandler;
......
private AsyncExecutor() {
       mainHandler = new Handler(Looper.getMainLooper(), this);
}
......

第三,要能监听Activity的生命周期,所以要用Application注册生命周期回调ActivityLifecycleCallbacks。

......
private Lifecycle lifecycle;
......
lifecycle = new Lifecycle();
activity.getApplication().registerActivityLifecycleCallbacks(lifecycle);
......
private class Lifecycle implements Application.ActivityLifecycleCallbacks {
......
}

第四,定义异步任务回调接口类:
runBefore在异步任务开启前执行,运行在UI线程;
running在异步任务开启后执行,运行在异步线程;
runAfter在异步任务执行完成之后即running运行完之后执行,运行在UI线程。

public static abstract class AsyncCallback<T>  {
        protected boolean stop = false;
        Object t;
        protected void runBefore() {};
        protected abstract T running();
        protected abstract void runAfter(T t);
} 

第五,用HashMap<Integer, List<AsyncCallback>缓存当前Activity的所有异步任务回调,这里用Integer作为key来保存Activity的hashcode,并不是直接保存Activity,降低内存泄露的风险,缓存异步回调的用处就是,当监听到Activity的onDestroy时,拦截所有还未执行running的异步回调,直接结束这些异步任务,已经在执行running的异步回调,需要在异步回调实现类中,判断AsyncCallback的变量stop为true时,编写终止任务的逻辑,避免Activity内存泄露。当然这里提供了方法setStopOnLifecycleEvent来设置在哪个生命周期(除了onCreate,默认在onDestroy)拦截终止异步回调的执行。

......

    public static final int ON_CREATE = 11;
    public static final int ON_START = 12;
    public static final int ON_RESUME = 13;
    public static final int ON_PAUSE = 14;
    public static final int ON_STOP = 15;
    public static final int ON_DESTROY = 16;

    private HashMap<Integer, List<AsyncCallback>> activityCallbackCache = new HashMap<>();

    /**
     * @param onLifecycleEvent {@link AsyncExecutor#ON_START}, {@link AsyncExecutor#ON_RESUME}, 
     * {@link AsyncExecutor#ON_PAUSE}, {@link AsyncExecutor#ON_STOP}, {@link AsyncExecutor#ON_DESTROY}
     */ 
    public void setStopOnLifecycleEvent(int onLifecycleEvent) {
        if (onLifecycleEvent == ON_START
                || onLifecycleEvent == ON_RESUME
                || onLifecycleEvent == ON_PAUSE
                || onLifecycleEvent == ON_STOP
                || onLifecycleEvent == ON_DESTROY) {
            this.stopOnLifecycleEvent = onLifecycleEvent;
        }
    }

    private void checkStopOnLifecycleEvent(Activity activity, int onLifecycleEvent) {
        if (stopOnLifecycleEvent == onLifecycleEvent) {
            if (activityCallbackCache.containsKey(activity.hashCode())) {
                mainHandler.removeMessages(activity.hashCode());
                List<AsyncCallback> list = activityCallbackCache.get(activity.hashCode());
                for (AsyncCallback callback: list) {
                    callback.stop = true;
                }
                activityCallbackCache.remove(activity.hashCode());
            }
        }
    }

......
private class Lifecycle implements Application.ActivityLifecycleCallbacks {
        @Override
        public void onActivityCreated(Activity activity, Bundle savedInstanceState) {}
        @Override
        public void onActivityStarted(Activity activity) {
            checkStopOnLifecycleEvent(activity, ON_START);
        }
        @Override
        public void onActivityResumed(Activity activity) {
            checkStopOnLifecycleEvent(activity, ON_RESUME);
        }
        @Override
        public void onActivityPaused(Activity activity) {
            checkStopOnLifecycleEvent(activity, ON_PAUSE);
        }
        @Override
        public void onActivityStopped(Activity activity) {
            checkStopOnLifecycleEvent(activity, ON_STOP);
        }
        @Override
        public void onActivitySaveInstanceState(Activity activity, Bundle outState) {}

        @Override
        public void onActivityDestroyed(Activity activity) {
            checkStopOnLifecycleEvent(activity, ON_DESTROY);
        }
}

完整的代码实现

GitHub地址:github.com/xiepeijie/A…