Source understand AsyncTask

Simple to understand the next AsyncTask source, as after a review.

package: android.os;

Function: During asynchronous request to resolve the communication between the child thread and the main thread and so on.

Such as: an abstract class, and therefore can not be instantiated, we need to inherit from it and re-use.

Source resolve

AsyncTask class includes:
  • Static inner class 3 [AsyncTaskResult, InternalHandler, SerialExector]
  • A static inner abstract class [WorkerRunnable]
  • An enumeration class [Status]
Thread Pool section:
1
2
3
4
5
6
7
8
9
10
11
12
/**
* An {@link Executor} that can be used to execute tasks in parallel.
*/
public static final Executor THREAD_POOL_EXECUTOR;

static {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
sPoolWorkQueue, sThreadFactory);
threadPoolExecutor.allowCoreThreadTimeOut(true);
THREAD_POOL_EXECUTOR = threadPoolExecutor;
}

These parameters:

1
2
3
4
5
6
7
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();

Private static Final int CORE_POOL_SIZE Math.max = ( 2 , Math.min (CPU_COUNT - . 1 , . 4 )); // Maximum number of threads times the number of pool 2 of the core cpu. 1 + Private static Final int MAXIMUM_POOL_SIZE CPU_COUNT * = 2 + 1 ; // non-core number of threads survival time was 30s Private static Final int KEEP_ALIVE_SECONDS = 30 ;




1
2
3
Blocking queue length is 128 
Private static Final BlockingQueue <the Runnable> = sPoolWorkQueue new new a LinkedBlockingQueue <the Runnable> ( 128 );

Use in important ways:
1
2
3
4
5
6
7
8
// operation before beginning the task need: the main thread 
protected void () {}
// abstract class must implement. Consuming operation: child thread
protected abstract the Result the doInBackground ( the Params ... the params ) ;
// progress of the background task execution, for displaying a progress bar: the main thread
protected void onProgressUpdate ( Progress ... values ) {}
// task after the completion of the operation performed, you need to call: main thread
protected void onPostExecute ( the Result Result ) {}
execute execution method:
1
2
3
4
5
6
7
8
The first: we need to pass parameters scheduler and 
public Final the AsyncTask < Params , Progress, the Result > executeOnExecutor (Executor Exec, Params ... params ) The second: the internal call first way, using the default scheduler, parameters passed to public Final the AsyncTask < the Params , Progress, the Result > execute ( the Params ... the params ) third: The method of runnable default scheduler performs public static void execute (the Runnable runnable)






Default Scheduler: sDefaultExecutor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;

public static final Executor SERIAL_EXECUTOR = new SerialExecutor();

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 {
r.run();
} finally {
scheduleNext();
}
}
});
if (mActive == null) {
scheduleNext();
}
}

protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}

SerialExecutor Introduction

  1. SerialExecutor by ArrayDeque queue management Runnable when we start a lot of tasks, the first run in the first execute () method when invoked offer ArrayDeque's () method to add incoming Runnable object to the tail of the queue and then determine mActive the object is not equal to null, null is certainly the first run, so call scheduleNext () method. The queues value from the head, and assigned to mActive object and then call THREAD_POOL_EXECUTOR.execute (mActive) method, to perform Runnable object retrieved.
  2. execute and scheduleNext are synchronized modified, these two methods have the same object lock, can not run at the same time, in the execute method, r.run () method is time-consuming tasks sub-thread, when the execution is completed, the final will enter into finally call scheduleNext to remove a top task.
  3. Big Box  AsyncTask Source understand mTasks.offer to the task each time are placed in the tail ArrayDeque ensure a first-come, first it is executed.
executeOnExecutor()方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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:"
+ " the task is already running.");
case FINISHED:
throw new IllegalStateException("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;
}

executeOnExecutor方法中执行了onPreExecute(),然后执行了exec.execute(mFuture);

其中Future为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
mFuture = new FutureTask<Result>(mWorker) {

protected void done() {
try {
postResultIfNotInvoked(get());
} catch (InterruptedException e) {
android.util.Log.w(LOG_TAG, e);
} catch (ExecutionException e) {
throw new RuntimeException("An error occurred while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
}
}
};

从executeOnExecutor方法执行中可以看出,AsyncTask内,在主线程中先执行了onPreExecute()方法,然后在线程中调用了doInBackground()方法,任务执行完成后,通过postResult 或者 postResultIfNotInvoked 方法发送消息到主线程

postResult方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
private void postResultIfNotInvoked(Result result) {
final boolean wasTaskInvoked = mTaskInvoked.get();
if (!wasTaskInvoked) {
postResult(result);
}
}

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

postResult方法的作用即为任务结束后,发送message给主线程,反馈Result结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private static class InternalHandler extends Handler {
public InternalHandler(Looper looper) {
super(looper);
}

@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})

public void handleMessage(Message msg) {
AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;
switch (msg.what) {
case MESSAGE_POST_RESULT:
// There is only one result
result.mTask.finish(result.mData[0]);
break;
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;
}
}
}

接收结果的为InternalHandler类,接收到结果并调用mTask的finish方法并把结果返回过去。

finish方法
1
2
3
4
5
6
7
8
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}

当Task结束后,会调用finish方法,如AsyncTask已经被取消,则会返回onCancelled回调,当未被取消则会调用onPostExecute回调。因此,onPostExecute回调也是主线程。

总结:

In the past has been used AsyncTask, but also know how to call, but did not know how it works, after we analyze the source code can be seen, AsyncTask for us to do a good thread management (abuse of threads in the application, it will cause too many threads causing serious problems), it provides pre-execution, execution progress bar update, after performing the callback operations, facilitated our use.

Guess you like

Origin www.cnblogs.com/sanxiandoupi/p/11711195.html