Said in the previous

As anyone who has used AsyncTask knows, AsyncTask is designed to perform time-consuming tasks on an asynchronous thread so as not to block the UI thread. However, some disadvantages are found in the process of using it:

  1. Personally, I feel AsyncTask is a bit expensive to learn because it takes three generic parameters.
  2. When AsyncTask is used in an Activity, it is easy to cause memory leaks. Because AsyncTask is often used as an internal class of the Activity, sometimes the execution time of the asynchronous task is tens of seconds or even longer. When the page is closed, If the asynchronous task does not end and holds a reference to the Activity, the Activity cannot be reclaimed in time, resulting in a memory leak.
  3. An AsyncTask is not bound to a life cycle. It cannot automatically terminate an asynchronous task based on the life cycle.

Due to the disadvantages of AsyncTask, I want to implement a lightweight AsyncTask by myself.

How is AsyncTask implemented

First, need to be able to carry out an asynchronous task, first of all, the internal implementation need to be able to open a new thread to execute, and then to be able to multi-task concurrent, and the number of concurrent threads shoulds not be too much, so think of using the thread pool, use fixed number of threads thread pool, number of concurrent threads control for? Well, of course is set to the number of CPU cores is appropriate.

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

Second, the asynchronous task should be able to be cut back to the UI thread, so use a UI thread Handler.

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

Third, to monitor the Activity of the life cycle, so use Application lifecycle callback ActivityLifecycleCallbacks registration.

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

Fourth, define the asynchronous task callback interface class: runBefore is executed before the asynchronous task starts and runs in the UI thread. Running Runs on an asynchronous thread after an asynchronous task is started. RunAfter is executed after the execution of the asynchronous task is complete, i.e. after the running run, and runs in the UI thread.

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

Fifth, use HashMap<Integer, List<AsyncCallback> to cache all asynchronous task callbacks for the current Activity. To reduce the risk of memory leaks, caching asynchronous callbacks is useful. When listening to the Activity’s onDestroy, intercept all asynchronous callbacks that have not yet executed running, and end those asynchronous tasks directly. If the AsyncCallback variable stop is true, write the logic to terminate the task to prevent the Activity from leaking memory. Of course, the setStopOnLifecycleEvent method is provided to set which lifecycle (except onCreate, which defaults to onDestroy) intercepts and terminates the execution of the asynchronous callback.

.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); }}Copy the code

Complete code implementation

GitHub address: github.com/xiepeijie/A…