Simple Example
Here directly to the previous written a small demo, according to the demo to analyze the source code.
Public class mainactivity extends actionbaractivity {... Private Myasynctask Asynctask;protected voidOnCreate (Bundle savedinstancestate) {... asynctask =NewMyasynctask ();//Click button to perform an asynchronous taskButton.setonclicklistener (NewOnclicklistener () {... asynctask.execute ("Leelit");//This parameter is passed in parameter, commonly used in URL network download, can be empty. } }); }/* Generic class Asynctask has three parameters: Params, incoming parameters, Progress, progress, result, return results. You can also use void to indicate that the parameter is empty. */ Private class myasynctask extends asynctask<String, Void, String> {@OverrideprotectedString Doinbackground (String ... string) {//TODO auto-generated method stubString conutstring = string[0];//String variable parameter intz =0;//Perform 500 million calculations to simulate a time-consuming task for(inti =0; I <1000000; i++) { for(intj =0; J < -; J + +) {z++; }} conutstring + ="has executed + + computation for"+ z +"Times"; LOG.E ("ProcessInfo","The task is done");returnconutstring;//Returns the result of the calculation to OnPostExecute ()} @Overrideprotected voidOnPostExecute (String result) {//TODO auto-generated method stub Super. OnPostExecute (Result); Textview.settext (result);//Refresh UI} } }
Process
- First step: Instantiate Myasynctask, enter Asynctask constructor
Public Asynctask() {Mworker =NewWorkerrunnable<params, result> () { PublicResultPager() throws Exception {mtaskinvoked.Set(true); Process.setthreadpriority (Process.thread_priority_background);//noinspection Unchecked returnPostresult (Doinbackground (mparams)); } }; Mfuture =NewFuturetask<result> (mworker) {@Overrideprotected void Done() {Try{postresultifnotinvoked (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) {postresultifnotinvoked (NULL); } } }; }
As you can see, the constructors of Asynctask are mainly instantiated mWorker and mFuture two objects, and look at the classes that these two objects belong to.
privatestaticabstractclass WorkerRunnable<Params, Result> implements Callable<Result> { Params[] mParams; }
Workerrunnable is an abstract class, implements the callable interface, needs to rewrite the call method inside the subclass, and has the parameter field inside. While this abstract method returns postResult(doInBackground(mParams)) , the Postresult method returns a result and internally sends the result to the main thread through handler. The Mfuture object can be seen as a wrapper over the Mworker object.
privatepostResult(Result result) { @SuppressWarnings("unchecked") Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT, new AsyncTaskResult<Result>(this, result)); message.sendToTarget(); return result; }
- Step Two: Execute Execute method
public final AsyncTask<Params, Progress, Result> execute(Params...params) { returnparams); }
This method continues to call the Executeonexecutor method
PublicFinal Asynctask<params, Progress, result>Executeonexecutor(Executor exec, Params ...params) {if(Mstatus! = status.pending) {Switch(Mstatus) { CaseRUNNING:Throw NewIllegalStateException ("Cannot execute task:"+"The task is already running."); CaseFinished:Throw NewIllegalStateException ("Cannot execute task:"+"The task has already been executed"+"(a task can be executed only once)"); }} mstatus = status.running; OnPreExecute (); Mworker.mparams =params; Exec.execute (mfuture);return This; }
The parameters passed in are sDefaultExecutor and params , as a result of this method, the task is only executed once, otherwise throws an exception.
executeOnExecutormethod to:
mStatus = Status.RUNNING, set the status of the task
onPreExecute(), calling this potentially overridden method, which is also the first step in user perception
mWorker.mParams = params, set the parameters for the task
exec.execute(mFuture), to perform this task, also said that the mfuture can be regarded as a mworker package.
Next look at the last exec.execute(mFuture) method, note this execute refers to sDefaultExecutor the execute method, which is easy to be confused with Asynctask's Execute method.
publicstaticvoidexecute(Runnable runnable) { sDefaultExecutor.execute(runnable); }
Focus on the Sdefaultexecutor this class
privatestaticvolatile Executor sDefaultExecutor = SERIAL_EXECUTOR;publicstaticfinalnew SerialExecutor();
Sdefaultexecutor is a Serialexecutor object, followed by the Serialexecutor class.
Private Static class serialexecutor implements Executor { FinalArraydeque<runnable> Mtasks =NewArraydeque<runnable> (); Runnable mactive; Public synchronized void Execute(FinalRunnable r) {Mtasks.offer (NewRunnable () { Public void Run() {Try{R.run (); }finally{Schedulenext (); } } });if(Mactive = =NULL) {Schedulenext (); } }protected synchronized void Schedulenext() {if((mactive = Mtasks.poll ())! =NULL) {Thread_pool_executor.execute (mactive); } } }
Step-by-step, the final Execute method is to perform the task through a task queue and a thread pool, and the thread pool is all different in different version parameters.
publicstaticfinal Executor THREAD_POOL_EXECUTOR new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
Finally, let's see how handler handles the message.
Private Static class internalhandler extends Handler { Public Internalhandler() {Super(Looper.getmainlooper ()); }@SuppressWarnings({"Unchecked","Rawuseofparameterizedtype"})@Override Public void 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; } } }
You can see that there are two States, representing the completion of the MESSAGE_POST_RESULT task, call the method at this time, the finish main logic inside the method is to call the OnPostExecute () method, and MESSAGE_POST_RESULT represents the progress, at this time the call is the onProgressUpdate method.
Obviously, when we call publishprogress in the overridden Doinbackground method, Handler sends a MESSAGE_POST_PROGRESS message containing the state.
protectedfinalvoidpublishProgress(Progress... values) { if (!isCancelled()) { getHandler().obtainMessage(MESSAGE_POST_PROGRESS, new AsyncTaskResult<Progress>(this, values)).sendToTarget(); } }
Summary
- Instantiate Asynctask object, construct method inside instantiate Mworker object and Mfuture object, Mworker object is an object that implements callable interface, call method calls
postResult(doInBackground(mParams) , The Postresult method sends a message to the main thread via handler, and then encapsulates the Mworker object with a Mfuture object.
- Execute Asynctask.execute (params) method
- Execution Executeonexecutor (sdefaultexecutor, params);
- Execute
onPreExecute method, set mworker parameter, call Sdefaultexecutor.execute (mfuture);
THREAD_POOL_EXECUTOR.execute(mActive), use a thread pool to 串行 perform the task.
Execution process:
- Myasynctask.execute (Parmas ...) ;
- OnPreExecute (), set mworker/mfuture parameters;
- Sdefaultexecutor.execute (mfuture), the internal is a serial execution of the task of the thread pool, and the task is the 2nd step to rewrite the Doinbackground method;
- Executes the task Postresult (Doinbackground (params))/publishprogress (Progress ... values), sending a message to the main thread via handler.
Before the 3.0 release, the task can be executed concurrently, 3.0 is serial, if we need to execute the task concurrently after the 3.0 version, we can call Executeonexecutor (asynctask.thread_pool_executor,params) Without having to internally maintain the sdefaultexecutor of a serial task queue.
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
Android:asynctask Source Code Analysis