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.