In the process of Android application development, we need to keep an eye on the stability of the application and the timely response of the UI operation, because the unstable or slow response of the application will give the application a bad impression, serious users uninstall your app, so your efforts will not reflect the value of. This paper tries to explain the internal realization mechanism from the role of Asnyctask. If you have some experience in the development of people, after reading should be used in the process of asnyctask some of the problems to be enlightened, the development experience is not rich can also find the use of attention points in the process.
 
 
 
Why introduce Asnynctask?
When the Android program starts running, a single process is started, and by default all of the program actions are performed in this process. An Android program has only one process by default, but a process can have threads.
In these threads, there is a thread called the UI thread, also called the main thread, which can be called worker thread except for threads other than main thread. Main thread is responsible for controlling the UI page display, update, interaction and so on. Therefore, the shorter the action requirement in the UI thread, the better, the more smooth the user will feel. A good practice is to encapsulate some of the more time-consuming operations, such as network requests, database operations, and complex computations, into separate threads so that the main thread can be avoided. For this reason, someone has written the following code:
PrivateTextView TextView; Public void onCreate(Bundle bundle) {Super. OnCreate (bundle);        Setcontentview (R.LAYOUT.THREAD_ON_UI); TextView = (TextView) Findviewbyid (r.id.tvtest);NewThread (NewRunnable () {@Override             Public void Run() {Try{HttpGet HttpGet =NewHttpGet ("Http://www.baidu.com"); HttpClient HttpClient =NewDefaulthttpclient (); HttpResponse Httpresp = Httpclient.execute (HttpGet);if(Httpresp.getstatusline (). Getstatuscode () = = $) {String result = entityutils.tostring (Httpresp.getentity (),"UTF-8"); Textview.settext ("The request returns to normal and the result is:"+ result); }Else{Textview.settext ("The request returned an exception!" "); }                }Catch(IOException e)                {E.printstacktrace ();    }}). Start (); }
Run, as expected, the exception information is as follows:
thethatits views.
How did it break? The handler object can be created on the main thread, replacing the Textview.settext place with handler to send the return value back to the thread where the handler is located, that is, the main process. This approach is slightly more complicated, and Android gives us a lightweight asynchronous class that can directly inherit Asynctask, implement asynchronous operations in the class, and provide interface feedback on the results of the current asynchronous execution and the progress of the execution, which are directly running in the main thread. , such as the Onpostexecute,onpreexecute method.
In other words, the Android program is multithreaded, in order to more easily handle the interaction of child threads and UI threads, Asynctask is introduced.
Asnynctask internal mechanism
Asynctask internal logic consists of two parts:
1, the interaction with the main line , it instantiates a static custom class Internalhandler, this class is inherited from the handler, in this custom class is bound to an object called Asynctaskresult, Each time a child thread needs to notify the main thread, it calls Sendtotarget to send a message to handler. Then in handler's Handlemessage asynctaskresult do different things depending on the type of message (for example, Messagepostprogress will update the progress bar, Messagepostcancel cancel the task). It is worth mentioning that these actions are performed on the UI thread, meaning that the handler object is automatically called from the child thread once it is required to interact with the UI thread, placing the message on the main thread. Source Address
Mfuture =NewFuturetask<result> (mworker) {@Overrideprotected voidMore ... Done() {Message message; Result result =NULL;Try{result =Get(); }Catch(Interruptedexception e)               {ANDROID.UTIL.LOG.W (Log_tag, E); }Catch(Executionexception e) {Throw NewRuntimeException ("An error occured while executing doinbackground ()", E.getcause ()); }Catch(Cancellationexception e) {message = Shandler.obtainmessage (Message_post_cancel,NewAsynctaskresult<result> (Asynctask. This, (result[])NULL)); Message.sendtotarget ();return; }Catch(Throwable t) {Throw NewRuntimeException ("An error occured while executing"+"Doinbackground ()", t); } message = Shandler.obtainmessage (Message_post_result,NewAsynctaskresult<result> (Asynctask. This, result));           Message.sendtotarget (); }        };
  Private Static  class internalhandler extends Handler {        @SuppressWarnings({"Unchecked","Rawuseofparameterizedtype"})@Override         Public voidMore ...Handlemessage(Message msg) {Asynctaskresult result = (Asynctaskresult) msg.obj;Switch(msg.what) { CaseMessage_post_result://There is only one resultResult.mTask.finish (result.mdata[0]); Break; CaseMESSAGE_POST_PROGRESS:result.mTask.onProgressUpdate (Result.mdata); Break; CaseMESSAGE_POST_CANCEL:result.mTask.onCancelled (); Break; }        }    }
2,asynctask internal scheduling , although you can create more than one instance of Asynctask subclasses, but Asynctask's internal handler and threadpoolexecutor are static, so defined variables belong to the class is a process-wide shared, so Asynctask controls all instances of subclasses within the process, and all instances of that class share a thread pool and handler. The code is as follows:
 Public Abstract classAsynctask<params, Progress, result> {Private StaticFinal String Log_tag ="Asynctask";Private StaticFinalintCore_pool_size =5;Private StaticFinalintMaximum_pool_size = -;Private StaticFinalintKeep_alive =1;Private StaticFinal blockingqueue<runnable> Sworkqueue =NewLinkedblockingqueue<runnable> (Ten);Private StaticFinal Threadfactory sthreadfactory =NewThreadfactory () {PrivateFinal Atomicinteger MCount =NewAtomicinteger (1); PublicThread More ...Newthread(Runnable R) {return NewThread (R,"Asynctask #"+ mcount.getandincrement ()); }    };Private StaticFinal Threadpoolexecutor Sexecutor =NewThreadpoolexecutor (Core_pool_size, Maximum_pool_size, Keep_alive, Timeunit.seconds, SWorkQueue, SThreadFactory) ;Private StaticFinalintMessage_post_result =0x1;Private StaticFinalintMessage_post_progress =0x2;Private StaticFinalintMessage_post_cancel =0x3;
As you can see from the code, the size of the default core thread pool is 5, and the cache task queue is 10. This means that if the thread pool has fewer than 5 threads, a new asynchronous task will create a new thread at this time, and if the number of thread pools is greater than or equal to 5, a new asynchronous task will be placed in the cache queue for execution. Restricting the number of threads in an app's asynctask may seem necessary, but it also poses a problem if someone needs to run 10 instead of 5, or limit the number of threads, such as the loading of n multiple images in some app's waterfall stream pages.
On the other hand, at the same time running many tasks, threads are more, if these tasks are to access the network, will lead to a short period of time the phone that poor bandwidth is accounted for, so the overall performance of who are hard to quickly load completely, because they are competitive relationship. So, give the choice to the developer.
In fact, probably starting with Android from 3.0, each time you create a new asynchronous task, the Asnyctask internal default rule is to run only one asynchronous task at a time in the order in which it was committed. Of course, you can also specify your own thread pool yourself.
It can be seen that there are a lot of places to pay attention to during the Asynctask
 
 
  
  - Because handler needs to interact with the main thread, and handler is built into Asnyctask, Asynctask must be created in the main thread.
- The Asynctaskresult Doinbackground (Mparams) method executes an asynchronous task that runs in a child thread, and other methods run in the main thread to manipulate the UI component.
- Do not manually call Asynctask's OnPreExecute, Doinbackground, publishprogress, Onprogressupdate, OnPostExecute method, These are automatically called by the Android system.
- A task Asynctask task can only be executed once.
- You can cancel a task at any time by calling the Cancel (Boolean) method in the run, if the successful call to IsCancelled () returns True, and the OnPostExecute () method is not executed, instead of calling the Oncancelled () method. And from the source, if this task has been executed at this time call cancel will not really end the task, but continue to execute, but change is the execution of the callback method is OnPostExecute or oncancelled.
Asnynctask and Activity Onconfiguration
There are so many points of attention mentioned above, do you have anything else to pay attention to? Of course! When we use Asynctask to request network data in the process of developing the app, it is customary to show the progress bar in OnPreExecute, OnPostExecute close the progress bar after the data request is completed. This may seem perfect, but if your app does not explicitly specify screen orientation and configchanges, the activity restarts when the user rotates the screen, and this time your asynchronous load data thread might be requesting the network. When a new activity is re-created, a new task may be restarted to request the network, so that a previous asynchronous task inadvertently leaked, assuming you still write some other logic in OnPostExecute, this time there will be unexpected exceptions.
Generally simple data types, dealing with configchanges we are good at handling, we can directly through Onsaveinstancestate () and Onrestoreinstancestate () to save and restore. Android will call the Onsaveinstancestate () method before destroying your activity, so you can store data about the state of the app in this method. You can then recover from the OnCreate () or Onrestoreinstancestate () method.
But what about the asynctask? The problem stems from the fact that the activity was destroyed during the re-creation process and the Asynctask and previous activity was lost, resulting in some problems. Then the idea of solving the problem can also be developed in this direction. The official Android documentation also has some clues to solve the problem.
Here is another solution that uses event bus, written by an android from abroad. In the middle of the square open source Eventbus class library http://square.github.io/otto/. First, customize a subclass of Asynctask, and in the OnPostExecute method, throw the return result to the event bus, the code is as follows:
 @Override    protectedStringDoinbackground(Void ... params) {Random random =NewRandom ();Final LongSleep = Random.nextint (Ten);Try{Thread.Sleep (Ten*6000); }Catch(Interruptedexception e)        {E.printstacktrace (); }return "Slept for"+ Sleep +"Seconds"; }@Override    protected void OnPostExecute(String result) {mybus.getinstance (). Post (NewAsynctaskresultevent (result)); }
The event bus is registered in the activity's oncreate so that the message of the asynchronous thread is Otta distributed to the currently registered activity, and this time the return result is in the current activity's Onasynctaskresult, the code is as follows:
 @Override    protected void onCreate(Bundle savedinstancestate) {Super. OnCreate (Savedinstancestate);        Setcontentview (r.layout.otto_layout); Findviewbyid (R.id.button). Setonclicklistener (NewView.onclicklistener () {@Override  Public void OnClick(View v) {NewMyasynctask (). Execute ();        }        }); Mybus.getinstance (). Register ( This); }@Override    protected void OnDestroy() {mybus.getinstance (). Unregister ( This);Super. OnDestroy (); }@Subscribe     Public void Onasynctaskresult(Asynctaskresultevent event) {Toast.maketext ( This, Event.getresult (), Toast.length_long). Show (); }
The personal feeling of this method is quite good, of course, you can not otta this library, their own individual use of the interface callback method can also be estimated to achieve, we can try.
 
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
 
Do you really understand the asynctask?