Android development: complete source code parsing of AsyncTask, androidasynctask

Source: Internet
Author: User

Android development: complete source code parsing of AsyncTask, androidasynctask

Since I was engaged in Java Development, I have been familiar with a lot of open-source code. I can understand the code myself, but it is a little difficult to express it. From today on, I gradually began to parse some open-source code and record it as a blog for sharing, hoping to improve my expression ability. If there is any error in the article, readers are welcome to point out in the comments so that I can correct them in time to avoid misleading other readers. If you have any better suggestions, you are welcome to leave your comments below. I am very honored. If you reprint this article, please bring it with youOriginal Text Link:Http://blog.csdn.net/d_clock/article/details/43805779Well, let's get started with this point.
As an Android developer, AsyncTask is not a stranger to the asynchronous operation class. This is one of the most controversial classes since I started to use android in my sophomore year. I have seen many people on the internet talking about the poor performance of AsyncTask and the high concurrency, many asynchronous operations in the code of the open-source framework I have read do not use AsyncTask. They all use Java thread pool operations, so that I have never used AsyncTask for a while, I think AsyncTask has many drawbacks. Then, a great god in the company said, "You didn't find that AsyncTask has encapsulated interaction between asynchronous threads and UI threads? Google provides this class for developers to use. "I think it makes sense to think about it carefully. In retrospect, the framework we saw previously uses a thread pool for asynchronous operations, basically, because none of these frameworks involve interaction with the UI, you can use the thread pool directly. So I took some time to think about the source code of AsyncTask (in fact, this code has been used many times, and there is always a new experience each time), and I am pulling a piece of content.
In daily development, the AsyncTask method is the same as the Demo Code provided in the official document. First, the AsyncTask class is inherited to implement the corresponding generic parameters and the doInBackground abstraction method is rewritten, this method is used to execute the asynchronous operation we need.

How can I use AsyncTask for asynchronous operations? It's very easy to use the official Demo Code.

You only need to generate this AsyncTask and call the execute parameter to input the corresponding parameter. This completes the asynchronous operation process and finally returns the result to the main thread where onPostExecute is located for processing, it is indeed very convenient to call to achieve interaction with two threads. At this point, we have reviewed the basic use of AsyncTask. If you are not familiar with Android programmers, you should think about it in the toilet.Finally, I have omitted some notes when using AsyncTask for programming.:

Next, let's look at the source code of AsyncTask. First, let's look at the constructor and related variables.

CPU_COUNT: Number of CPU Cores
CORE_POOL_SIZE: The number of concurrent threads in the thread pool, which is directly linked to the number of CPU cores.
MAXIMUM_POOL_SIZE: The maximum number of threads in the thread pool, which is directly linked to the number of CPU cores.
KEEP_ALIVE: Maximum Lifetime of threads in the thread pool
SThreadFactory: Used to construct the factory of the thread pool. The newThread method is rewritten to name each thread to facilitate debugging and tracking.
SPoolWorkQueue: Working queue in the thread pool, with a maximum capacity of 128 chained blocking queues
THREAD_POOL_EXECUTOR: Multi-task concurrent working thread pool. The initialization parameters are the preceding parameters.
SERIAL_EXECUTOR: Serial working thread pool. The implementation class is the following SerialExecutor.

SHandler: Handler used for thread interaction in the AsyncTask class. The implementation class is an internal class.InternalHandler(The implementation of AsyncTask is to encapsulate Thread and Handler for interaction, saving us the process of self-encapsulation)
MESSAGE_POST_RESULT: Type of the message returned by sHandler
MESSAGE_POST_PROGRESS: Type of the message in which sHandler returns the progress
SDefaultExecutor: The default thread pool of the AsyncTask class. By default, the SERIAL_EXECUTOR serial thread pool is used for initialization.
MWorker: Class that implements the Callable interface, which is initialized in the constructor.
MFuture: FutureTask instance, used together with mWorker, is also initialized in the following Constructor
MStatus: Mark the RUNNING status of the current AsyncTask, which can be PENDING, RUNNING, and FINISHED, respectively, to indicate waiting, RUNNING, and RUNNING.
MCancelled: The flag of the canceled running task
MTaskInvoked: Mark of the task that has been scheduled to run

At this point, we have roughly scanned some of the basic code. First, we can understand the above before we can easily understand the code process that we will continue to look at. We know that we need to execute an AsyncTask, after the new method is released, an asynchronous task starts when the execute method is called. Next, start with the execute code. The official documents show that there are two available execute methods, we usually call the one in the red box below.

Next we will follow up the code here and then look around.

You can see that the executeOnExecutor function is called in the execute function and the result is returned. The executeOnExecutor is used to execute a thread task in the thread pool, there are two input parameters. Apart from the variable-length parameter passed in by execute itself, it is the static variable sDefaultExecutor of the AsyncTask class. I have already introduced this static thread pool, by default, it is a single-task serial thread pool. Since executeOnExecutor is called, the code in executeOnExecutor can be viewed.

From the implementation of this function, after entering this function, we first start to judge the status of the currently executed AsyncTask. If it is PENDDING, it indicates that the current AsyncTask has never been executed, the mStatus status is directly marked as RUNNING. If AsyncTask has executed the execute method, the mStatus here will not directly throw an exception if it is another PENDDING status, this can clearly explain why an AsyncTask cannot call execute twice.

Because the PENDDING status has been set to another State during the first call, if the call is judged to be in a non-PENDDING state again, IllegalStateException is directly thrown.
After setting the mStatus status, the onPreExecute method will be called,

This method is actually an empty method. Because the method is still in the UI thread when the power is called, The AsyncTask subclass can override this method and implement some UI operations in it, this is also an extension method left behind when AsyncTask is designed. It can be used for some preparations before the asynchronous operation starts.

After that, the variable length parameter passed in from execute is stored in the member variable of mWorker, and the default serial thread pool is used for concurrent operations.

At this point, the executeOnExecutor function is basically complete. Next, continue to the exec code and return to the Code in SerialExecutor and the AsyncTask constructor, the mWorker class implementation code is browsed here

As you can see, WorkerRunnable is actually an abstract static internal class with mParams member variables and inherits Callable. mWorker is such an implementation instance, which can be seen in executeOnExecutor, the member variable mParams in mWorker is used to store the parameters we passed in during the execute call.

In the constructor, we can see that mWorker is instantiated and the call function in the Callable interface is implemented (this function is the same as the run function in the Runnable interface executed in the thread pool, but Callable can return the result state ), enter the code in executing the call function. First, set the flag bit indicating the invocation of the current task to true. Then, set the thread execution priority, at the beginning, we started to enter the most common doInBackground function, and passed in the parameters. How can we better understand the call process step by step, after doInBackground is executed, the execution result is returned as a parameter for calling the postResult function. In the postResult function, you will see Handler that we are more familiar, it returns the execution result in doInBackground to the Message Queue of our UI thread, And the handleMessage in Handler is used to call the finish method in AsyncTask, while the finish method is In the end, it will determine whether the doInBackground is properly executed or canceled midway through, so as to determine whether to call onCancelled or onPostExecute, finally, set the execution status of AsyncTask to FINISH to complete the interaction process between the entire asynchronous thread and the UI thread. Note that the done method in mFeture is mainly used to process the execution of the AsyncTask.



Note that the Message Type sent from postResult is MESSAGE_POST_RESULT. This type of message indicates that doInBackground is executed, but you can see that in the InternalHandler class above, in fact, there are two types of messages to be processed. The two types of messages are also mentioned in the previous section about member variables, another type of message is mainly used to update the progress of tasks executed in asynchronous tasks to the UI thread, for example, the example of updating the download progress that we most often encounter, actually, the following publishProgress method is continuously called in the doInBackground method, so you can also clearly see that it is actually sending MESSAGE_POST_PROGRESS messages using Handler, finally, update the onProgressUpdate method.


You can also see that the onProgressUpdate method is actually the method that AsyncTask left for us to extend and rewrite.

At this point, we have basically understood the entire working process of AsyncTask. Next we will look at AsyncTask's asynchronous concurrency. This time, I am not in a rush to read the code. Let's take a look at some of the APIS provided by Google.


AsyncTask provides two types of thread pools. We have already introduced the serial working thread pool and concurrent working thread pool. There are also two functions that execute AsyncTask, one is execute and the other is executeOnExecutor, we have also seen the above Code. In fact, we call execute. In the code, we also call the executeOnExecutor function. So I 'd like to tell you that this is related to AsyncTask's concurrent execution of asynchronous tasks? Let's go back to the Code in SerialExecutor.

All of our execute AsyncTask, in essence, are eventually packaged into a FutureTask and then executed in a Executor. If we do not specify this Executor, by default, SerialExecutor is used to execute these tasks. SerialExecutor uses an array queue ArrayDeque to organize these executed tasks. From the code, we can see that each task is executed, it will be deleted in ArrayDeque. You can run the next task only after the previous Runnable task is executed. If the previous task is not completed, then the subsequent tasks will never be executed, which explains why AsyncTask is not suitable for a long time-consuming task, because once a task takes too long, under the default AsyncTask execution mechanism, all subsequent tasks will never be executed. If you observe carefully, you will also see that the thread pool for AsyncTask execution is static class variables rather than member variables. Therefore, if a very time-consuming task occurs, it will be related to all AsyncTask issues in the app.
When Google first designed AsyncTask, it was mainly because the configuration of Android devices was still poor at the time, so it was not suitable for concurrent execution of too many tasks, for these reasons, AsyncTask is made into this serial execution task. However, with the development of hardware, Google also considers the multi-task concurrency problem faced by AsyncTask, therefore, another THREAD_POOL_EXECUTOR concurrent thread pool has been extended in Android3.0. However, according to the THREAD_POOL_EXECUTOR initialization parameter, Google still controls the number of tasks that AsyncTask executes simultaneously, and it is directly linked to the number of CPU cores. This also takes into account performance issues to some extent. Android3.0 expands the executeOnExecutor interface, you can even use the executeOnExecutor interface to define your own concurrent thread pool outside AsyncTask. At this point, the source code parsing of AsyncTask is almost coming to an end. Finally, I want to talk about the execution status of AsyncTask and cancel the AsyncTask being executed, for more information, see the following code.



So far, I am familiar with the basic operations and related execution procedures of the entire AsyncTask.
Finally, I would like to make a personal summary. From my personal development experience, the AsyncTask class has indeed been well encapsulated, the interaction between the asynchronous thread and the UI thread has been well processed, so developers can happily program the classes provided by Google. If you consider the number of concurrent tasks, you can also use interfaces provided after 3.0 to increase the number of concurrent operations, but we still need to properly control the maximum number of concurrent tasks, because a large number will also cause app performance problems, this is why the number of concurrent tasks in the multi-task thread pool provided by Google is directly linked to the number of CPU cores, and traces back to the essence of AsyncTask. We can also see from the source code clearly, it is actually a combination of FutureTask and Handler.
The source code parsing of AsyncTask ends here. I hope this article will help you better understand and use AsyncTask in Android development,In order to help you better clarify your ideas, I will write another blog to use a UML diagram to express the work process of AsyncTask, which will become more intuitive..Respect originality. for reprinting, please indicate the source:Http://blog.csdn.net/d_clock/article/details/43805779

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.