This article refers to API 29

1. Fundamentals

The basic principle of AsyncTask is as follows: Thread pool + Handler encapsulates two thread pools and one Handler. Thread pools are responsible for thread scheduling and task execution, and handlers are responsible for asynchronous communication.

Member variables The specific role
THREAD_POOL_EXECUTOR (thread pool) The thread that executes the task
SBackupExecutor (Thread pool) Use queues to coordinate task scheduling
mHandler Communication between a worker thread and the main thread

Main callback method

  • onPreExecute()
  • doInBackground(Params… params)
  • onProgressUpdate(Progress… values)
  • onPostExecute(Result result)
  • onCancelled(Result result)

OnPreExecute () -> doInBackground(Params… params) -> onPostExecute(Result result).

If the current task is cancelled by calling the cancel method, onPostExecute is replaced by onCancelled(Result Result)

In doInBackground you can also call onProgressUpdate(Progress… The values) method updates the task progress.

2. The analysis

AsyncTask constructor

The AsyncTask constructor creates Handler, WorkerRunnable, and FutureTask objects, respectively.

Three, the source code in the constructor, but actually can use only the AsyncTask (), the latter two were hide not call, this limits the Handler at the time of creation, must be in the UI thread.

  • AsyncTask()
  • AsyncTask(Handler handler)
  • AsyncTask(Looper callbackLooper)

The internal default Handler implementation code is as follows:

    private static class InternalHandler extends Handler {
        public InternalHandler(Looper looper) {
            super(looper);
        }

        @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
        @Override
        public void handleMessage(Message msg) {
            AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;
            switch (msg.what) {
                case MESSAGE_POST_RESULT:
                    // There is only one result
                    result.mTask.finish(result.mData[0]);
                    break;
                case MESSAGE_POST_PROGRESS:
                    result.mTask.onProgressUpdate(result.mData);
                    break;
            }
        }
    }
Copy the code

As you can see, the main thing is to send the result and update the Progress event.

WorkerRunnable is the Callable interface used to temporarily store Params[]. The Callable interface only has call().

private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
    Params[] mParams;
}
Copy the code

The Call () method is implemented when the WorkerRunnable object is created

mWorker = new WorkerRunnable<Params, Result>() { public Result call() throws Exception { //1. Modify whether the Task is invoked as true mTaskInvoked. Set (true); Result result = null; Try {/ / 2. Set the thread priority Process. SetThreadPriority (Process. THREAD_PRIORITY_BACKGROUND); Result = doInBackground(mParams); Binder.flushPendingCommands(); } catch (Throwable tr) {//4. Cancelled at true mCancelled. Set (true); throw tr; } finally {//5. Send result postResult(result); } return result; }};Copy the code

Create a FutureTask object that overwrites done(). Note that FutureTask passes in the WorkerRunnable sample object when it is created. In FutureTask’s run method, the WorkerRunnable call method is executed

mFuture = new FutureTask<Result>(mWorker) { @Override protected void done() { try { postResultIfNotInvoked(get()); } catch (InterruptedException e) { android.util.Log.w(LOG_TAG, e); } catch (ExecutionException e) { throw new RuntimeException("An error occurred while executing doInBackground()", e.getCause()); } catch (CancellationException e) { postResultIfNotInvoked(null); }}}; / / -- -- -- -- -- -- -- -- -- -- -- -- -- -- line -- -- -- -- -- -- -- -- -- -- -- -- -- -- private void postResultIfNotInvoked (Result Result) {/ / task execution tag, Final Boolean wasTaskInvoked = mTaskInvoked. Get (); if (! wasTaskInvoked) { postResult(result); }}Copy the code

FutureTask is a class that implements the Runnable and Future interfaces. It mainly maintains a state of the Task throughout the process, and the example object of FutureTask is ultimately executed in the execute() method.

execute()

Execute calls the executeOnExecutor method to add tasks to the thread pool of the task queue and execute tasks in sequence

For mStatus, each AsyncTask can be executed only once, and IllegalStateException will be thrown for executing or completed asyncTasks

@MainThread public final AsyncTask<Params, Progress, Result> execute(Params... params) { return executeOnExecutor(sDefaultExecutor, params); } @MainThread public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec, Params... params) { if (mStatus ! = Status.PENDING) { switch (mStatus) { case RUNNING: throw new IllegalStateException("Cannot execute task:" + " the task is already running."); case FINISHED: throw new IllegalStateException("Cannot execute task:" + " the task has already been executed " + "(a task can be executed only once)"); } } mStatus = Status.RUNNING; onPreExecute(); mWorker.mParams = params; exec.execute(mFuture); return this; }Copy the code

conclusion

AsyncTask is the thread scheduling and task state management for time-consuming operations. Although it is basically not used now, part of the code writing method is worth learning.