说在前面
用过AsyncTask的都知道,AsyncTask是为了在异步线程执行耗时任务以免阻塞UI线程而设计的。但是在使用过程中发现它存在一些缺点:
- 个人感觉AsyncTask学习成本有点高,因为它带三个泛型参数,学习成本略微有点高;
- AsyncTask在Activity中使用不注意容易造成内存泄露,因为AsyncTask时常被用作Activity的内部类来使用,有时由于某些原因造成异步任务的执行时间长达几十秒甚至更长,当页面关闭时,异步任务没结束并对Activity持有引用,Activity不能被及时回收,导致内存泄露。
- 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);
}
}
网友评论