asynctask, an asynchronous task, is a class that Android gives us to handle asynchronous tasks. This class enables the UI thread and the background thread to communicate, the background thread executes the asynchronous task, and returns the result to the UI thread. We know that in Android, only the UI thread, the main thread, can perform updates to the UI, while other threads cannot manipulate the UI directly. This benefit is to ensure the stability and accuracy of the UI and to avoid the UI clutter caused by multiple threads working on the UI at the same time. But Android is a multi-threaded operating system, we can not always put all the tasks are implemented in the main thread, such as network operations, file reading and other time-consuming operations, if all put in the main thread to execute, it may cause later task blocking. Android detects this blocking and throws a application not responsed (ANR) error when the blocking time is too long. So we need to put these time-consuming operations in a non-main thread to execute. This avoids the single-threaded model of Android, And to avoid the ANR. While doing Web requests now has a good library of volley family buckets and okhttp, Asynctask is needed to handle other background tasks and interact with the UI. Tens of millions of users of any product will never use the system in the code of the original Asyntask, because of its egg-ache compatibility and very high crash rate is really people dare not to compliment. Asynctask What exactly is it? It's simple, it's just a wrapper over the thread pool and handler, using a thread pool to handle background tasks, and using handler to handle interacting with the UI. The thread pool is using the executor interface, so let's take a look at the thread-pool features. One of the major improvements that
jdk5 brings is Java concurrency, which provides three concurrent weapons: The Concurrency Framework executor, Concurrent collection types such as Concurrenthashmap, concurrency control classes such as Countdownlatch, and so on, try to use exector instead of directly using the thread class for concurrent programming. The
Asynctask also uses a thread pool to handle concurrency, and the thread pool is constructed from the Threadpoolexector class, which allows developers to customize the thread pools by allowing them to be customized, so let's see what each of these parameters mean. Then see how Android is customized.
The other constructors of Threadpoolexecutor will eventually call the following constructor to complete the object creation work:
Public threadpoolexecutor (int corepoolsize,
int Maximumpoolsize,
Long KeepAliveTime,
Timeunit Unit,
Blockingqueue<runnable> WorkQueue,
Threadfactory Threadfactory,
Rejectedexecutionhandler handler);
corepoolsize: Number of core threads, even if the thread pool does not have a task, The core thread also does not terminate (unless the Allowcorethreadtimeout parameter is set) and can be understood as "resident thread"
maximumpoolsize: The maximum number of threads allowed in a thread pool; In general, the more threads there are, the greater the overhead of thread scheduling, so this is generally the limit.
KeepAliveTime: When the number of threads in the thread pool is more than the core thread, if the KeepAliveTime time is exceeded, the extra threads are recycled These threads that are relative to the core thread are often referred to as the cache thread
unit:keepalivetime time units
workQueue: Queue to save tasks before task execution; This queue only holds runnable tasks submitted by execute
Threadfactory: A factory used to construct a thread pool, usually using the default;
handler: How the thread pool is handled when the thread pool causes subsequent tasks to block due to the number of threads and queue constraints.
If the thread pool has fewer threads than corepoolsize, the thread pool will re-create a core thread even if there are other core threads that do nothing , until the number of core threads reaches Corepoolsize (resident thread in place). If the number of threads in the thread pool is greater than or equal to corepoolsize, but the work queue Workqueue is not full, then the new task is placed in the queue workqueue, followed by the FIFO principle to wait for execution. When a core thread finishes working on a task that is idle, it checks the task queue and then takes out the task silently, if the thread pool has a number of threads greater than or equal to corepoolsize, and the work queues Workqueue full, but the number of buses is less than maximumpoolsize. Then directly create a thread to handle the task being added. If the work queue is full and the number of threads in the thread pool reaches the maximum number of maximumpoolsize, then the last construction parameter is used handler processing; * * The default is to dispose of the task directly and throw an exception. In summary, that is to say, when there are new tasks to be processed, first look at whether the number of threads in the thread pool is greater than corepoolsize, and then see if the buffer queue WorkQueue is full, and finally see whether the number of threads in the thread pool is greater than maximumpoolsize. In addition, when the number of threads in the thread pool is greater than corepoolsize, if the thread's idle time exceeds keepalivetime, it is removed from the thread pool, so that the number of threads in the threading pools can be dynamically adjusted.
Asynctask There are "two" thread pools, one thread_pool_executor a serial_executor; Because in fact Serial_executor also use thread_pool_executor implementation, but added a queue to make a serial just. Asynctask inside the thread pool is a thread pool with a core number of threads of CPU + 1, a maximum number of threads for CPU * 2 + 1, a work queue length of 128, and no handler parameter, then the default handler (Deny execution) is used. If there are too many tasks, then the limit of the number of work queues and threads will cause this thread pool to block, then the tragedy occurs, and the default processing throws an exception directly causing the process to hang up. Assuming you write an asynchronous picture-loading frame yourself, and then implement it with Asynctask, it's easy to get this exception when you slide the ListView quickly, which is why the big imageloader are writing their own thread pool and handlder. This thread pool is a static variable, so within the same process, all local asynctask default constructors are constructed using the same thread pool, and if the app module is more and less controlled, it is easy to meet the first crash condition. If you unfortunately have access to shared resources in different Asynctask Doinbackgroud, then there will be a variety of concurrent programming problems.
After the completion of Asynctask all, the process will still be resident corepoolsize threads, under Android 4.4 (API 19), the corepoolsize is HardCode, the value is 5;API 19 changed to CPU + 1; that is, before Android 4.4, if you execute more than five asynctask and then do nothing, there will still be 5 asynctask threads in the process.
The handler in
Asynctask is simple, as follows (API 22 code):
private static final Internalhandler Shandler = new Internalhandler ();
Public Internalhandler () {
super (Looper.getmainlooper ());
}
Note that the looper of the main thread is directly used here; If you look at the code below API 22, you will see that it does not have this constructor, but instead uses the default; By default, Handler uses the looper of the current thread, if your asynctask is created on a child thread, Unfortunately, your onpreexecute and OnPostExecute are not executed on the UI thread, but are executed by the handler post to the thread that created it, and if you update the UI on these two threads, it is a direct result of a crash. This is why the Asynctask must be created in the main thread. In addition, the handler inside the asynctask is a static variable, that is, it is created when the class is loaded, and if you have never used Asynctask in your app's process before, then use the Asynctask related variables in the child thread. This causes the static handler to initialize, if under API 16, then the same problem arises, that is why the asynctask must be initialized in the main thread. In fact, after Android 4.1 (API 16), in the main function of the main thread of the app Activitythread, The Ascyntask.init function is called directly to ensure that the class is initialized on the main thread, and in addition, the INIT function obtains the Internalhandler looper, because it is executed in the main thread, so Asynctask handler is also the main thread looper. The problem has been solved completely.
The use of Asynctask is simple, only need to focus on three parameters and four methods.
Asynctask<params,progress,result> is an abstract class that is typically used for inheritance. The inheritance asynctask needs to specify the following three generic parameters:
Params: The type of parameter entered when the task is started.
Progress: The type of progress value returned in background task execution.
Result: The type of the result returned after the background task execution completes.
Asynctask mainly have the following methods:
Doinbackground: You must override the task that executes the background thread asynchronously, and the time-consuming operation is done in this method.
OnPreExecute: Called before a background time-consuming operation is performed, typically for initialization operations.
OnPostExecute: When the Doinbackground method is complete, the system will call this method automatically and pass the value returned by the Doinbackground method to this method. This method is used to update the UI.
Onprogressupdate: This method is called when the Publishprogress method is called in the Doinbackground method to update the progress of the task execution. In this way we can know the progress of the task's completion.
The following code shows an example of a typical asynchronous process-loading a network picture. Network operations, as an unstable time-consuming operation, are prohibited from being placed in the main thread from 4.0 onwards. So when displaying a Web image, we need to download the picture in asynchronous processing and set the picture in the UI thread.
Mainactivity.java
Importandroid.app.Activity;Importandroid.content.Intent;ImportAndroid.os.Bundle;ImportAndroid.view.View;ImportAndroid.view.View.OnClickListener;ImportAndroid.widget.Button; Public classMainactivityextendsActivity {PrivateButton Btn_image; @Overrideprotected voidonCreate (Bundle savedinstancestate) {Super. OnCreate (savedinstancestate); Setcontentview (R.layout.activity_main); Btn_image=(Button) Findviewbyid (r.id.btn_image); Btn_image.setonclicklistener (NewOnclicklistener () {@Override Public voidOnClick (View v) {startactivity (NewIntent (mainactivity. This, Imageactivity.class)); } }); }}
Imageactivity.java
Importandroid.app.Activity;Importandroid.graphics.*;Importandroid.os.*;ImportAndroid.view.View;Importandroid.widget.*;ImportJava.io.*;Importjava.net.*; Public classImageactivityextendsActivity {PrivateImageView ImageView; PrivateProgressBar ProgressBar; Private StaticString URL = "Http://tupian.baike.com/a2_50_64_01300000432220134623642199335_jpg.html?prd=so_tupian"; @Overrideprotected voidonCreate (Bundle savedinstancestate) {Super. OnCreate (savedinstancestate); Setcontentview (R.layout.image); ImageView=(ImageView) Findviewbyid (r.id.image); ProgressBar=(ProgressBar) Findviewbyid (R.id.progressbar); //Start processing asynchronous tasks by calling the Execute method. Equivalent to the Start method in the thread. Newmyasynctask (). Execute (URL); } classMyasynctaskextendsAsynctask<string,void,bitmap> { //OnPreExecute for operations before asynchronous processing@Overrideprotected voidOnPreExecute () {Super. OnPreExecute (); //the ProgressBar is set to visible here.progressbar.setvisibility (view.visible); } //The processing of asynchronous tasks in the Doinbackground method.@OverrideprotectedBitmap doinbackground (String ... params) {//get the arguments passed inString URL = params[0]; Bitmap Bitmap=NULL; URLConnection connection; InputStream is; Try{Connection=Newurl (url). OpenConnection (); is=Connection.getinputstream (); //in order to see more clearly the wait operation to load the picture, the thread sleeps for 3 seconds.Thread.Sleep (3000); Bufferedinputstream bis=NewBufferedinputstream (IS); //parsing an input stream with the Decodestream methodBitmap =Bitmapfactory.decodestream (bis); Is.close (); Bis.close (); } Catch(IOException e) {e.printstacktrace (); } Catch(interruptedexception e) {e.printstacktrace (); } returnbitmap; } //OnPostExecute for UI updates. The parameter for this method is the value returned by the Doinbackground method.@Overrideprotected voidOnPostExecute (Bitmap Bitmap) {Super. OnPostExecute (bitmap); //Hide ProgressBarprogressbar.setvisibility (View.gone); //Update ImageViewImageview.setimagebitmap (bitmap); } }}
Learn more about the Asynctask in Android