自己实现轻量级的AsyncTask

作者: 萧雾宇 | 来源:发表于2017-08-06 15:20 被阅读294次

    说在前面

    用过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地址:https://github.com/xiepeijie/AndroidAsyncExecutor

    相关文章

      网友评论

      • JarryLeo:少了一个功能啊,不能实现进度展示,AsyncTask 的 onProgressUpdate 方法没有实现哦

      本文标题:自己实现轻量级的AsyncTask

      本文链接:https://www.haomeiwen.com/subject/imeglxtx.html