Android Asynctask Implementation Mechanism
Sample code:
Public final Asynctask<params, Progress, result> execute (Params ... Params) {return
executeonexecutor ( Sdefaultexecutor, params);
Public final Asynctask<params, Progress, result> executeonexecutor (Executor exec,
Params ... Params) {
if (Mstatus!= status.pending) {
switch (mstatus) {case
RUNNING:
throw new IllegalStateException ("Cannot execute task:"
+ "task is already running. ");
Case finished:
throw new IllegalStateException ("Cannot execute task:
+" The task has already been "executed" 15/>+ "(a task can be executed only once)");
}
Mstatus = status.running;
OnPreExecute ();
Mworker.mparams = params;
Exec.execute (mfuture);
return this;
}
Execute first invokes OnPreExecute (visible, OnPreExecute is called automatically) and then calls Exec.execute (Mfuture)
Public interface Executor {
void execute (Runnable command);
}
This is an interface, specifically implemented in
private static class Serialexecutor implements Executor {
final arraydeque<runnable> mtasks = new Arraydeque< ; Runnable> ();
Runnable mactive;
Public synchronized void Execute (final Runnable R) {
Mtasks.offer-new Runnable () {public
void run () {
try { C11/>r.run ();
} finally {
schedulenext ();
}}}
);
if (mactive = = null) {
schedulenext ();
}
}
protected synchronized void Schedulenext () {
if (mactive = Mtasks.poll ())!= null) {
Thread_pool_ Executor.execute (mactive);}}
From the above, asynctask execution process is as follows: First execute onpreexecute, then give serialexecutor execution. In the Serialexecutor, add the runnable to the Mtasks first.
If no runnable is executing, then the Serialexecutor Schedulenext is invoked. At the same time, when a runnable is finished, proceed to the next task
The asynctask has two thread pools, Thread_pool_executor and Serial_executor, and a Handler–internalhandler
/**
* A {@link Executor} that can is used to execute the tasks in parallel.
* * Public
static final Executor thread_pool_executor
= new Threadpoolexecutor (core_pool_size, Maximum_pool_ SIZE, Keep_alive,
timeunit.seconds, Spoolworkqueue, sthreadfactory);
/**
* A {@link Executor} that executes tasks one at the time of serial
* order. This serialization are global to a particular process.
* * Public
static final Executor serial_executor = new Serialexecutor ();
private static Internalhandler Shandler;
Serial_executor for the arrangement of tasks, thread_pool_executor true thread execution, Internalhandler for thread switching
First look at the constructor
Public Asynctask () {
mworker = new Workerrunnable<params, result> () {Public result call
() throws Exception {
Mtaskinvoked.set (true);
Process.setthreadpriority (process.thread_priority_background);
Noinspection unchecked return
postresult (Doinbackground (Mparams));
}
;
Mfuture = new Futuretask<result> (mworker) {
@Override
protected void Done () {
try {
Postresultifnotinvoked (Get ());
} catch (Interruptedexception e) {
ANDROID.UTIL.LOG.W (Log_tag, E);
} catch (Executionexception e) {
throw New RuntimeException ("An error occured while executing doinbackground ()",
E.getcause ());
Cancellationexception e) {
postresultifnotinvoked (null);}}
;
}
See the familiar doinbackground, and then call Postresult
Private result Postresult {
@SuppressWarnings (' unchecked ') message message
= GetHandler (). Obtainmessage (Message_post_result,
new asynctaskresult<result> (this, result));
Message.sendtotarget ();
return result;
}
The main thread creates the Internalhandler and sends the MESSAGE_POST_RESULT message, and then calls the Finish function
private static class Internalhandler extends Handler {public
Internalhandler () {
super (Looper.getmainlooper () );
}
@SuppressWarnings ({"Unchecked", "Rawuseofparameterizedtype"})
@Override public
void Handlemessage msg) {
asynctaskresult<?> result = (asynctaskresult<?>) msg.obj;
Switch (msg.what) {case
Message_post_result:
//There be only one result
result.mTask.finish ( Result.mdata[0]);
break;
Case message_post_progress:
result.mTask.onProgressUpdate (result.mdata);
break;
}
}} private void finish (result result) {
if (iscancelled ()) {
oncancelled (result);
} else {
OnPostExecute (result);
}
Mstatus = status.finished;
}
Call OnPostExecute in finish.
Asynctask Workflow: New Mythread (). Execute (1);
Constructor first, then execute
Constructor just prepares the two variables mworker and mfuture
In Execute, call OnPreExecute, then Exec.execute (mfuture), which responds to the call function, calls Doinbackground, and then passes the result to handler and then finish, Finish function Call OnPostExecute
You may wonder why there is no onprogressupdate, and there are annotations that can explain
/**
* runs on the UI thread after {@link #publishProgress} is invoked.
* The specified values are the values passed to {@link #publishProgress}.
*
* @param values the values indicating progress.
* *
@see #publishProgress
* @see #doInBackground
/@SuppressWarnings ({"Unuseddeclaration"})
protected void Onprogressupdate (Progress ... values) {
}
This means that publishprogress must be invoked to automatically invoke Onprogressupdate.
So how do you call publishprogress?
/**
* Override to perform a computation on a background thread. The
* Specified parameters are the parameters passed to {@link #execute} * By the caller of this
task.
* This method
can call {@link #publishProgress} to publish updates * on the
UI thread.
*
* @param params the parameters of the task.
*
@return A result, defined by the subclass of this task.
* *
@see #onPreExecute ()
* @see #onPostExecute
* @see #publishProgress
/
protected abstract Result Doinbackground (Params ... Params);
Doinbackground said very clearly, in the Doinbackground function inside the display call publishprogress can.
Publishprogress Source:
protected final void publishprogress (Progress ... values) {if (!iscancelled ()) { GetHandler (). Obtainmessage (Message_post_progress, New asynctaskresult<progress> (this, values)). SendToT
Arget (); } private static Class Internalhandler extends Handler {public Internalhandler () {Super (LOOPER.GETMAINL
Ooper ()); @SuppressWarnings ({"Unchecked", "Rawuseofparameterizedtype"}) @Override public void Handlemessage (Message m
SG) {asynctaskresult<?> result = (asynctaskresult<?>) msg.obj; Switch (msg.what) {case Message_post_result://There be only one result Result.mTask.finish (
Result.mdata[0]);
Break Case Message_post_progress://**************************************** here to call RESULT.MTASK.ONPROGRESSUPD
Ate (Result.mdata);
Break }
}
}
Thank you for reading, I hope to help you, thank you for your support for this site!