The author blog

http://www.cherylgood.cn/

directory

  1. preface

  2. AsyncTask knowledge supplement

  3. Precautions for using AsyncTask

  4. Analyze the source code of AsyncTask from daily use

  5. I want AsyncTask to run in parallel, ok?

  6. conclusion

preface

AsyncTask, you are familiar with it. You may be lucky enough to know that AsyncTask pits you already have, or you may not know it yet!

In this article, I will take a look at how AsyncTask is dug.

Without saying anything, let’s look at some code first.

1. Create an AsyncTask class

Suppose you run it like this

3. What do you think will happen?

  • Before Android3.0 the execution time is the same, after Android3.0 each execution time difference of 2 seconds;

  • Although android3.0 has basically no adaptation, but we know it is still good oh.

2

AsyncTask knowledge supplement

(Skip this section if you are already familiar with AsyncTask.)

  • Before we look at AsyncTask pits, let’s take a look at the source code to help us understand why AsyncTask is a pit and how to deal with it, or you can skip to the next chapter.

  • In order to help developers simplify the thread switching problem, the system provides a lightweight AsyncTask. The evolution of AsyncTask has gone through several iterations, creating a hole that is easy to ignore.

  • As a lightweight asynchronous task class, AsyncTask is popular among Android developers. Use AsyncTaskNike to perform background tasks in the thread pool and pass the progress and final results of the trip to the UI thread for further action.

  • In essence, AsyncTask also encapsulates Thread and Handler. Previously, we analyzed and learned the implementation process of Handler through the source code of Handler in “Android Development Handler History”. Small partners in need can click on it, there are bad places welcome to leave a message oh.

  • Everyone knows AsyncTask is an abstract class, generally we inherit the AsyncTask to create our AsyncTask, and create time we need to provide three generic parameter (~ ~ | | I suspect if I was in a blind force force), these three generic parameter with AsyncTask not shallow.

  1. Params: represents the type of argument we pass when we call the execute method;

  2. Progress: indicates the progress type of background tasks.

  3. Result: Indicates the returned Result type of background tasks.

(Unneeded data can be set to Void.)

  • AsyncTask also provides the following methods:

  1. OnPreExecute (): This method is called in the main thread, and you can write some logic inside the method such as displaying loading animations;

  2. DoInBackground: This method is executed in a child thread and is generally used to write operations that need to be performed in the child thread. If you need to update your progress, call the publishProgress method, which calls the onProgresssUpdate method. The publishProgress method is called with a progress value, which is eventually called in onProgresssUpdate. Why do you do that? Since onProgresssUpdate is executed on the main thread, only the main thread can update the UI. Of course when you do doInBackground you need to return a result set. The result set is finally fetched in onPostExecute. For the same reason, onPostExecute is run in the main thread; (Thread switching back and forth is annoying, isn’t it?)

  3. OnProgresssUpdate: we’ve done this before, but we’ll skip it here;

  4. OnPostExecute: also onPostExecute;

  5. OnCancelled: executes in the main thread. The asynchronous task is destroyed when it is cancelled. Now onPostExecute is not going to be called.


3

Precautions for using AsyncTask

  1. The AsyncTask class must first be loaded in the main thread (we don’t need to do this, ActivityThread already does this for us);

  2. The AsyncTask creation code must be called in the main thread;

  3. The execute method must be called in the main thread;

  4. OnPreExecute, onPostExecute, doInBackground and onProgressUpdate cannot be called directly in the program.

  5. An AsyncTask instance can only call the execute method once;

  6. AsyncTask executes execute method in serial before Android1.6; Android1.6 after parallel; Android3.0 post-serial.

4

Analyze the source code of AsyncTask from daily use

If you are using AsyncTask with the execute method, let’s start with it.

So let’s go into the body of the execute method and see, what’s going on in there?

I’ll start with an annotation from @mainThread. What is this? I haven’t used it.

In fact, it is an annotation provided by Google, indicating that our method must be called in the main thread, if not, AS will remind us in red.

Execute (executeOnExecutor); execute (executeOnExecutor);

1. SDefaultExecutor (what is this?)

Params is a variable parameter passed from execute.

OK, the key is sDefaultExecutor, from the name to see sDefaultExecutor is a grinding executor meaning, but we are very serious people, so must see sDefaultExecutor is what east east, so funny force funny force to find the relevant code.

OK, as you can see from its definition, sDefaultExecutor is an instance of the Executor type, obtained through SerialExecutor (). So what does SerialExecutor () do?

As you can see from the above code, there is an array queue for mTasks. When we call Execute, we insert a runnable instance into the mTasks queue. That is, mTasks holds threads, which may surprise you, Tasks.offer(new Runnable()) ¶ Public synchronized void execute(final Runnable r) ¶

OK, I put a more detailed analysis in the code.

OK, let’s go back to the executeOnExecutor method.

Summary:

Execute (AsyncTask) is executed sequentially in an ArrayQueue by default. SDefaultExecutor is a serial executor, so our AsyncTask is serial by default.

OK, let’s take a closer look at the AsyncTask execution process. First, let’s look at what the AsyncTask constructor does.

Create a WorkerRunnable (Result = doInBackground(mParams)); PostResult (result) is always called; Methods.

Exec. Execute (mFuture); create a FutureTask object. The argument passed in indicates that mFuture is an instance of type runnable. If the mWorker is created, the runable thread will execute the work in the mWorker, so our doInBackground method will execute in the Runable thread.

OK, we just talked about how our code goes into the child thread, but we didn’t see the code that starts the child thread. We can see that he ends up calling the postResult method.

OK, you can see that inside, we are familiar with the Handler to implement oh. So let’s see, we passed MESSAGE_POST_RESULT and AsyncTaskResult, so this is our AsyncTask, and then we call some AsyncTask method in this handler, so let’s look at getHandler ().

OK, so there’s an instance of InternalHandler inside. And InternalHandler looks like this.

The MESSAGE_POST_RESULT method corresponds to the finish method. This is the finish method of our AsyncTask.

As you can see, onCancelled(result) will eventually be called; Or onPostExecute (result);

Summary:

Creating an AsyncTask creates an mWorker and an mFuture, which is an object of type runable and will eventually be put into an execution queue for execution when we execute- executeOnExecutor. The onPreExecute() method is called before passing. When the mFuture is executed, it calls back to mWorker’s call method, which calls doInBackground. The postResult method is called after obtaining the result of doInBackground execution. PostResult internally switches threads through handler, and finally calls our Finish method. Finish will call onCancelled(result) or onPostExecute(result); One of them. This completes one of the key processes of our AsyncTask.

5

I want AsyncTask to run in parallel, ok?

Of course you can. We’ve looked at serial versus parallel, the key is the actuator. Since sDefaultExecutor is passed in by default, sDefaultExecutor is a serial executor, so we pass in a parallel executor, is that ok?

We can see that AsyncTask also provides a THREAD_POOL_EXECUTOR, which can be used to make execute work in parallel, according to annotations

/**

* An {@link Executor} that can be used to execute tasks in parallel.

*/public static final Executor THREAD_POOL_EXECUTOR;

THREAD_POOL_EXECUTOR = THREAD_POOL_EXECUTOR = THREAD_POOL_EXECUTOR = runable;

Why is SerialExecutor serial? THREAD_POOL_EXECUTOR, however, is fetched from the queue, one at a time, and the second at a time.

6

conclusion

Through this learning, we learned about the workflow of AsyncTask from creation to execution, and why it is executed serially by default. Of course, to parallel is also very simple, you can customize the actuator, to control themselves, but generally do not need (~ ∇). Through this learning, I believe that you will be more practical when using AsyncTask. Thick and thin hair!

Related to recommend

Android development Handler history

Feel free to appreciate the article if it has been useful to you.

Reward

people gave a reward

Long press the QR code to transfer money to me

Feel free to appreciate the article if it has been useful to you.