Asynctask basic usage and source code analysis in Android (API 23)

Source: Internet
Author: User

Original link Http://sparkyuan.github.io/2016/03/23/AsyncTask Source analysis (API 23)/reprint please indicate the source

The Android UI is thread insecure, and if you want to update the UI in a child thread, you must use the asynchronous operating mechanism of Android, and updating the UI directly in the main thread causes the program to crash.
There are two main types of asynchronous operations for Android, Asynctask and handler. Asynctask is a lightweight, asynchronous class that is simple and controllable. This article mainly combines the source code of API 23 to explain what Asynctask is.

Basic usage

Disclaimer: Android Different API version of the same class implementation may be different, this article is based on the latest API 23 source to explain.

publicabstractclass AsyncTask<Params, Progress, Result>

Params: Parameters passed in at execution time
Progress: Execution progress of background tasks
Result: Return value

Asynctask is an abstract class, so you need to define a class to inherit from him, like

class MyAsyncTask extends AsyncTask<Void, Integer, Boolean>
Asynctask the execution process:
    1. Execute (params ... params) to perform an asynchronous task.
    2. OnPreExecute (), executed after the Execute (params ... params) is invoked, the initialization of the interface, such as displaying a progress bar dialog box, and so on.
    3. Doinbackground (params ... params), executed after OnPreExecute () is completed to perform a more time-consuming operation, without returning the result of a task execution if the third generic parameter of asynctask specifies void. You can call Publishprogress (Progress. Values) during execution to update the progress information. Note that the UI action is not available in this method .
    4. Onprogressupdate (Progress. Values), when you call Publishprogress (Progress ... values), this method is executed to update the progress information to the UI component.
    5. OnPostExecute (result result), when the background operation ends, this method will be called, the result will be passed as a parameter to this method, you can use the returned data to do some UI operations, such as reminding the results of task execution, and closing the Progress Bar dialog box.
Example

Create a new activity, a button and a ProgressBar, click button to start a asynctask and update the status of ProgressBar in real time.

Myasynctask
Class Myasynctask extends Asynctask<void, Integer, boolean> {@Override        protected void OnPreExecute() {Super. OnPreExecute (); }@Override        protected void OnPostExecute(Boolean Aboolean) {Super. OnPostExecute (Aboolean); }@Override        protected void onprogressupdate(Integer ... values) {Super. onprogressupdate (values); Progressbar.setprogress (values[0]); }@Override        protectedBooleanDoinbackground(Void ... params) { for(inti =0; I < -; i++) {//Call publishprogress, trigger Onprogressupdate methodPublishprogress (i);Try{Thread.Sleep ( -); }Catch(Interruptedexception e)                {E.printstacktrace (); }            }return true; }@Override        protected void oncancelled() {Super. oncancelled (); Progressbar.setprogress (0); }    }
Button's Click Method
startAsyncBtn.setOnClickListener(new View.OnClickListener() {            @Override            publicvoidonClick(View v) {                new MyAsyncTask();                myAsyncTask.execute();            }        });
SOURCE Analysis

The above example shows that the asynctask is very simple to use, it is convenient to create a new child thread in the main thread to update the UI and other operations. But his implementation is not as simple as the use, the following is the asynctask of the source of the analysis.

The Asynctask constructor
 Public Asynctask() {Mworker =NewWorkerrunnable<params, result> () { PublicResultPager()throwsException {Mtaskinvoked.set (true); Process.setthreadpriority (Process.thread_priority_background);//noinspection UncheckedResult result = Doinbackground (mparams); Binder.flushpendingcommands ();returnPostresult (result);        }        }; Mfuture =NewFuturetask<result> (Mworker) {@Override            protected void  Done() {Try{postresultifnotinvoked (get ()); }Catch(Interruptedexception e)                {ANDROID.UTIL.LOG.W (Log_tag, E); }Catch(Executionexception e) {Throw NewRuntimeException ("An error occurred while executing doinbackground ()", E.getcause ()); }Catch(Cancellationexception e) {postresultifnotinvoked (NULL);    }            }        }; }

Only two things were done in the constructor, initializing Mworker and mfuture two variables. Mworker is a callable object, Mfutre is a Futuretask object. Execute () is used.

Execute (params ... params)
publicfinalexecute(Params... params) {        return executeOnExecutor(sDefaultExecutor, params);    }

With only one line of code, the Executeonexecutor method is called, and Sdefaultexecutor is actually a serial thread pool, and all asynctask in a process are queued for execution in this serial thread sink. Executeonexecutor source code is as follows.

 Public FinalAsynctask<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; }

You can see that OnPreExecute () is called in this method, and then the execution of the one by one thread pool is analyzed under Exec.execute (mfuture).

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); }        }    }

The

System first encapsulates the Asynctask params parameter as a Futuretask object, Futuretask is a concurrency class, where it is equivalent to runnable And then handing Futuretask to Serialexecutor's Execute method, which first inserts futuretask into task queue tasks, if there is no active asynctask task at this time, The next Asynctask task is executed, and Asynctask will continue to perform other tasks until all tasks are executed when a Asynctask task is completed. as you can see from here, Asynctask is serially executed by default
Take a look at Asynctask's constructor, Mfuture constructs the mwork as a parameter, and the Mfuture Run method calls the Mwork call () method, and so called () is eventually executed in the thread pool. Call () calls Doinbackground () and returns the result to Postresult.

privatepostResult(Result result) {        @SuppressWarnings("unchecked")        Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,                new AsyncTaskResult<Result>(this, result));        message.sendToTarget();        return result;    }

You can see that a handler is obtained through GetHandler () in Postresult.

  privatestaticgetHandler() {        synchronized (AsyncTask.class) {            ifnull) {                new InternalHandler();            }            return sHandler;        }    }

View GetHandler source code, you can find GetHandler returned is a internalhandler, and then look at the source of Internalhandler.

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; }        }    }

See here has been enlightened, Internalhandler is an inherited handler class, in his Handlemessage () method of the MSG is judged, if it is Message_post_result executed finish (), If it is message_post_progress, execute onprogressupdate ().
Message_post_progress news is sent in the publishprogress, the details see source code.

protectedfinalvoidpublishProgress(Progress... values) {        if (!isCancelled()) {            getHandler().obtainMessage(MESSAGE_POST_PROGRESS,                    new AsyncTaskResult<Progress>(this, values)).sendToTarget();        }    }
Finish ()
privatevoidfinish(Result result) {        if (isCancelled()) {            onCancelled(result);        else {            onPostExecute(result);        }        mStatus = Status.FINISHED;    }

If the current task is canceled, the oncancelled () method is called, if OnPostExecute () is not called.

Precautions
    1. The Asynctask class must be loaded in the main thread, which has been automatically completed by the system in Android version 4.1 and above.
    2. The Asynctask object must be created in the main thread, and the Execute method must be called in the UI thread.
    3. A Asynctask object can only be executed once, that is, it can only be invoked once, otherwise it will report a run-time exception.
The differences between the different versions

Prior to Android 1.6, Asynctask was a serial task, and Android 1.6 started using the thread pool for parallel processing tasks, but starting with Android 3.0, to avoid concurrency errors caused by asynctask, the Asynctask Asynctask also uses a thread to perform the task serially. Nonetheless, in Android 3.0 and later, we can use Asynctask's Executeonexecutor method to perform tasks in parallel. But this method is a new addition to Android 3.0 and cannot be used on a low version.

Summarize

The whole asynctask of the source code has been analyzed, in the analysis of the source can be found, asynctask and nothing mysterious, his essence is handler.
We now know how to use Asynctask, each method will be called at what time, what role, what connection between each other, I believe we will encounter asynctask any problems are no longer afraid, because the asynctask the entire source has turned a bottom, What's so scary about it?

Original link Http://sparkyuan.github.io/2016/03/23/AsyncTask Source analysis (API 23)/reprint please indicate the source

Asynctask basic usage and source code analysis in Android (API 23)

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.