Reprinted from http://blog.csdn.net/liuhe688/article/details/6532519
stay Android There are two ways to implement asynchronous task mechanism, Handler and AsyncTask.
Handler mode needs to create a new thread for each task. After the task is completed, it sends a message to the UI thread through the Handler instance to complete the update of the interface. This method has fine control over the whole process, but it also has shortcomings. For example, the code is relatively bulky, and it is not easy to control the thread accurately when multiple tasks are executed at the same time. Knowledge about Handler It's also introduced in the previous section. If you don't know it, you can refer to it.
To simplify the operation, Android 1.5 provides the tool class android.os.AsyncTask, which makes it easier to create asynchronous tasks without writing task threads and Handler instances.
Let's first look at the definition of AsyncTask:
The three generic types represent "input parameters for starting task execution", "progress of background task execution" and "types of background calculation results". In certain situations, not all types are used, if not, they can be used. Java The. lang.Void type is replaced.
The execution of an asynchronous task generally consists of the following steps:
1.execute(Params... params), to perform an asynchronous task, we need to call this method in the code, trigger the execution of the asynchronous task.
2.onPreExecute(), which is executed immediately after execute(Params... params) is called, is generally used to mark the UI before performing background tasks.
3.doInBackground(Params... params), which is executed immediately after onPreExecute() is completed, is used to perform more time-consuming operations. This method receives input parameters and returns the calculation results. PushProgress (Progress... values) can be called during execution to update progress information.
4.onProgressUpdate(Progress... values), which is executed when publishProgress(Progress... values) is called, updates progress information directly to UI components.
5.onPostExecute(Result result), when the background operation is finished, this method will be called. The result of calculation will be passed as a parameter to this method, and the result will be displayed directly on the UI component.
When using it, there are several points that need special attention:
1. Instances of asynchronous tasks must be created in UI threads.
2. The execute (Params... params) method must be invoked in the UI thread.
3. Do not manually call onPreExecute(), doInBackground(Params... params), onProgressUpdate(Progress... values), onPostExecute(Result result).
4. The information of UI components cannot be changed in doInBackground(Params... params).
5. A task instance can only be executed once, and an exception will be thrown if executed the second time.
Next, let's look at how to use AsyncTask to perform asynchronous task operations. First, we build a project with the following structure:
The structure is relatively simple. Let's first look at MainActivity.java's code:
The layout file main.xml code is as follows:
Because we need to access the network, we also need to add permission to access the network in AndroidManifest.xml:
Let's look at the runtime interface:
These screenshots are the initial interface, the interface when performing asynchronous tasks, the interface after successful execution, and the interface after canceling tasks. After successful execution, the whole process log is printed as follows:
If we press the cancel button while performing the task, the log will be printed as follows:
You can see that the onCancelled() method will be called, and the onPostExecute(Result result) method will no longer be called.
The basic application of AsyncTask is introduced above. Some friends may wonder how AsyncTask is executed internally. What is the difference between the execution process of AsyncTask and the use of Handler? The answer is: AsyncTask is a good encapsulation of Thread+Handler, which can still be seen in android.os.AsyncTask code. Here's a detailed introduction to the implementation principle of AsyncTask.
Let's first look at the outline view of AsyncTask:
We can see that there are several key steps in the method, doInBackground(Params... params) is an abstract method, we must override this method when we inherit AsyncTask; onPreExecute(), onProgressUpdate(Progress... values), onPostExecute(Result result), onCancelled() are empty, we can selectively override them when we need them. PushProgress (Progress... Values) is final ized and cannot be overridden. It can only be invoked. We usually use doInBackground(Params... This method is called in params; in addition, we can see that there is an enumeration class for Status and a getStatus() method. The code snippet for the enumeration class for Status is as follows:
As you can see, the initial state of AsyncTask is PENDING, which represents the undetermined state, RUNNING represents the execution state, FINISHED represents the end state. These states are used in many places in the life cycle of AsyncTask, and they are very important.
After introducing the related content of outline view, we will focus on the execution process of AsyncTask from execute(Params... params). Let's take a look at the code segment of execute(Params... params):
There are three unfamiliar variables involved in the code: mWorker, sExecutor, mFuture. We will also take a look at their Lushan reality:
For sExecutor, it is an example of java.util.concurrent.ThreadPoolExecutor, which manages thread execution. The code is as follows:
mWorker is actually an implementation object instance of an abstract inner class of AsyncTask, which implements the call() method in the Callable < Result > interface. The code is as follows:
And mFuture is actually an example of java.util.concurrent.FutureTask. Here's the information about its FutureTask class:
You can see that FutureTask is a class for asynchronous computing that can be cancelled halfway.
The following are examples of mWorker and mFuture in AsyncTask:
We see in the code above that in the done() method of the mFuture instance object, if an exception of CancellationException type is caught, a message of "MESSAGE_POST_CANCEL" is sent; if it is successfully executed, a message of "MESSAGE_POST_RESULT" is sent, and the message is associated with an sHandler object. This sHandler instance is actually an instance of the internal class InternalHandler of AsyncTask, which inherits Handler. Let's analyze its code below:
We see that when we process a message and encounter "MESSAGE_POST_RESULT", it calls the finish() method in AsyncTask. Let's look at the definition of finish() method:
The original finish() method is responsible for calling the onPostExecute(Result result) method to display the results and change the status of the task.
In addition, in the done() method of the mFuture object, when constructing a message, the message contains an AsyncTaskResult type object, and then in the handleMessage(Message msg) method of the sHandler instance object, the object attached to the message is obtained in the following way:
What exactly is this Async Task Result and what does it contain? In fact, it is also an internal class of AsyncTask, a class used to wrap execution results. Let's look at its code structure:
To see that this AsyncTask Result encapsulates an instance of AsyncTask and some kind of data set, let's look at the code when building the message:
How to use this object when processing messages? Let's take a look at it again.
Generally speaking, when we call the execute(Params... params) method, the execute method calls the onPreExecute() method, and then the ThreadPoolExecutor instance sExecutor executes a FutureTask task, in which the doInBackground(Params... params) will be invoked if the developer overwrites the IndoBackground (Params... The publishProgress(Progress... values) method is invoked in the params method, and a MESSAGE_POST_PROGRESS message is sent through the sHandler instance sHandler to update the progress. The onProgressUpdate(Progress... values) method is invoked when sHandler processes the message; if an exception is encountered, a MESSAGE_POST_CANCEL message is sent to cancel the task and sHandler processes the message. The onCancelled() method will be invoked; if the execution is successful, a message of MESSAGE_POST_RESULT will be sent, showing the result that onPostExecute(Result) is used when sHandler processes the message. The result) method is called.
After the introduction above, I believe that friends have realized the essence of AsyncTask. It encapsulates Thread+Handler well, reduces the complexity of developers to deal with problems, and improves the efficiency of development. I hope that friends can appreciate it more.