This is the sixth day of my participation in Gwen Challenge
One of the ways to do source code analysis is not to obsess over what each line of code represents, but to understand the main flow and learn the design ideas behind it. And with the analysis of AsyncTask source code. After the analysis, I really benefited a lot. Although I did not know much about some threads, I gained a new understanding of the overall design and process. So in order to share what I learned next, I will write it down and hope that you can learn something as well.
Note that AsyncTask is deprecated in SDK30 and above and is not recommended for development.
First, after creating an AsyncTask, implement the specific method and call the execute() method to execute it.
The AsyncTask cannot be called again and onPreExecute() will be called first.
// 1. The initial value of the running Status is status.pending
private volatile Status mStatus = Status.PENDING;
@MainThread
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec, Params... params) {
if(mStatus ! = Status.PENDING) {switch (mStatus) {
case RUNNING:
// 2. If the command is executing, an error message is displayed
throw new IllegalStateException("Cannot execute task:"
+ " the task is already running.");
case FINISHED:
// 3. An error message is displayed if the AsyncTask execution is complete
throw new IllegalStateException("Cannot execute task:"
+ " the task has already been executed "
+ "(a task can be executed only once)"); }}// 4. Change the status
mStatus = Status.RUNNING;
Call onPreExecute()
onPreExecute();
mWorker.mParams = params;
// 6. Execute mFuture in the thread pool
exec.execute(mFuture);
return this;
}
Copy the code
Now look at exec.execute(mFuture); The thread related knowledge will not be discussed for the moment, we will only look at the overall process. A search shows that the mFuture is initialized in the constructor as follows.
public AsyncTask(@Nullable Looper callbackLooper) {
// 1. Obtain handler
mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
? getMainHandler()
: new Handler(callbackLooper);
// 4. MWorker and mFuture define thread-specific operations
mWorker = new WorkerRunnable<Params, Result>() {
public Result call(a) throws Exception {
mTaskInvoked.set(true);
Result result = null;
try {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
// 5. Execute the doInBackground method, which is already in the child thread
result = doInBackground(mParams);
Binder.flushPendingCommands();
} catch (Throwable tr) {
mCancelled.set(true);
throw tr;
} finally {
// 6. Send the result
postResult(result);
}
returnresult; }}; mFuture =new FutureTask<Result>(mWorker) {
@Override
protected void done(a) {
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); }}}; }// 2. A Handler singleton is provided
private static Handler getMainHandler(a) {
synchronized (AsyncTask.class) {
if (sHandler == null) {
sHandler = new InternalHandler(Looper.getMainLooper());
}
returnsHandler; }}// 3. You can see that Handler is implemented and the callback handling methods are defined
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; }}}// 7. Send the execution result to message, which is called back to comment 3 above.
private Result postResult(Result result) {
@SuppressWarnings("unchecked")
Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}
Copy the code
At this point, the basic execution process is complete, and there is another way to update the status that is actually done by sending a message.
@WorkerThread
protected final void publishProgress(Progress... values) {
if(! isCancelled()) { getHandler().obtainMessage(MESSAGE_POST_PROGRESS,new AsyncTaskResult<Progress>(this, values)).sendToTarget(); }}Copy the code
Simple analysis down, the overall process has an understanding, of course, it involves some thread related knowledge is not a lot of understanding, but this does not hinder us.
Good article to end here, I hope to help you.