展会信息港展会大全

Android-AsyncTask源码解析
来源:互联网   发布日期:2016-01-14 12:42:00   浏览:1140次  

导读:public final AsyncTaskParams, Progress, Result execute(Params... params) { return executeOnExecutor(sDefaultExecutor, params);//sDefaultExecutor? } private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR; public static final E...

public final AsyncTask<Params, Progress, Result> execute(Params... params) {

return executeOnExecutor(sDefaultExecutor, params);//sDefaultExecutor?

}

private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;

public static final Executor SERIAL_EXECUTOR = new SerialExecutor();

private static class SerialExecutor implements Executor { //严格来说它不是一个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);//最终执行任务的executor

}

}

}

public static final Executor THREAD_POOL_EXECUTOR

= new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,

TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);//这才是真正的executor,而且是static的,kvm里面唯一的一个!

private static final int CORE_POOL_SIZE = 5;//5个常驻线程

private static final int MAXIMUM_POOL_SIZE = 128;// 最多可以开到128个线程

//以上几行就解释了为什么无论执行多少次new AsynTask(),在DDMS只能看到5个Asyn的线程。

//ps:android的ThreadPoolExecutor和jdk的ThreadPoolExecutor接口长得一样,内部实现完全不一样。

sThreadFactory:

private static final ThreadFactory sThreadFactory = new ThreadFactory() {

private final AtomicInteger mCount = new AtomicInteger(1);

public Thread newThread(Runnable r) {

return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());

}

};

这就是为什么DDMS看到的Asyn线程的名字都带有"AsyncTask #"的前缀。

继续:

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();//abstract,可以被覆盖

mWorker.mParams = params;//mWorker?

exec.execute(mFuture);//exec就是前面提到的sDefaultExecutor,mFutrue?

return this;

}

在构造函数里面:

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));//这里首先调用子类的doInBackground()方法,然后调用postResult()

}

};

mFuture = new FutureTask<Result>(mWorker) {

@Override

protected void done() {//FutureTask执行完以后的回调

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

} catch (CancellationException e) {

postResultIfNotInvoked(null);

}

}

};

}

我们继续从exec.execute(mFuture);这一行往下看:

执行:sDefaultExecutor.execute(mFuture),实际上就是把任务入队,然后顺序的取,放到THREAD_POOL_EXECUTOR执行

执行:THREAD_POOL_EXECUTOR.execute(mFuture)这里会使用内部的线程来执行任务

try {

r.run();//r=mFuture

} finally {

scheduleNext();

}

从这里开始,下面的操作就是在单独的线程上执行了,执行任务实际就是直接调用run:mFuture.run(),这里面会调用mWorker.call():

public Result call() throws Exception {

mTaskInvoked.set(true);//这是个boolean的标志,private final AtomicBoolean mTaskInvoked = new AtomicBoolean();

Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);

//noinspection unchecked

return postResult(doInBackground(mParams));//这里首先调用doInBackground()方法,然后调用postResult()。我们一般会在子类重写doInBackground()方法

}

private Result postResult(Result result) {//在这里发消息

@SuppressWarnings("unchecked")

Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,//sHandler?

new AsyncTaskResult<Result>(this, result));//AsyncTaskResult?

message.sendToTarget();

return result;

}

private static class AsyncTaskResult<Data> {

final AsyncTask mTask;

final Data[] mData;

AsyncTaskResult(AsyncTask task, Data... data) {

mTask = task;

mData = data;

}

}

详细过程:

public class FutureTask<V> implements RunnableFuture<V> :

public void run() {

if (state != NEW ||

!UNSAFE.compareAndSwapObject(this, runnerOffset,

null, Thread.currentThread()))

return;

try {

Callable<V> c = callable;//是构造函数传进来的,mWorker实现了Callable接口,private static abstract class WorkerRunnable<Params, Result> implements Callable<Result>

if (c != null && state == NEW) {

V result;

boolean ran;

try {

result = c.call();//这里会调用mWorker.call(),

ran = true;

} catch (Throwable ex) {

result = null;

ran = false;

setException(ex);

}

if (ran)

set(result);//这里会设置执行的结果

}

} finally {

// runner must be non-null until state is settled to

// prevent concurrent calls to run()

runner = null;

// state must be re-read after nulling runner to prevent

// leaked interrupts

int s = state;

if (s >= INTERRUPTING)

handlePossibleCancellationInterrupt(s);

}

}

protected void set(V v) {

if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {

outcome = v;

UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state

finishCompletion();

}

}

private void finishCompletion() {

// assert state > COMPLETING;

for (WaitNode q; (q = waiters) != null;) {

if (UNSAFE.compareAndSwapObject(this, waitersOffset, q, null)) {

for (;;) {

Thread t = q.thread;

if (t != null) {

q.thread = null;

LockSupport.unpark(t);

}

WaitNode next = q.next;

if (next == null)

break;

q.next = null; // unlink to help gc

q = next;

}

break;

}

}

done();//这里会回调done()方法

callable = null;// to reduce footprint

}

在done()里面会再次判断是否发送过消息,如果没有,再次发送:

private void postResultIfNotInvoked(Result result) {

final boolean wasTaskInvoked = mTaskInvoked.get();//标志位

if (!wasTaskInvoked) {

postResult(result);

}

}

下面看下message的发送部分:

private Result postResult(Result result) {//在这里发消息

@SuppressWarnings("unchecked")

Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,//sHandler?

new AsyncTaskResult<Result>(this, result));

message.sendToTarget();

return result;

}

private static final InternalHandler sHandler = new InternalHandler();

private static class InternalHandler extends Handler {

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

@Override

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;

}

}

}

收到消息以后,如果是成功的,调用:

result.mTask.finish(result.mData[0]);

执行了mTask的finisk(),同时把执行结果传递进去

private void finish(Result result) {

if (isCancelled()) {

onCancelled(result);

} else {

onPostExecute(result);

}

mStatus = Status.FINISHED;

}

执行: onPostExecute(result);也就是我们在子类需要重写的方法,在这里就可以更新UI了。

从上面可以看出来个问题:

AsynTask内部是用一个线程池在执行任务,但是任务执行完毕以后,并没有提供一个关闭线程池的操作,因此,线程会一直存在。

如果想在任务结束以后把线程池一道关闭掉,可以调用两个参数的构造函数,把手动构造的Executor传递进去。

参考:http://stackoverflow.com/questions/8792799/android-doesnt-terminate-asynctask-thread-after-onpostexecution

而且官方文档里面说:

AsyncTask is designed to be a helper class around Thread and Handler and does not constitute a generic threading framework.

AsyncTasks should ideally be used for short operations (a few seconds at the most.)

If you need to keep threads running for long periods of time,

it is highly recommended you use the various APIs provided by the java.util.concurrent pacakge such as Executor, ThreadPoolExecutor and FutureTask.

AsyncTask只是一个帮助类,并不是一个通用的线程框架,它只适合执行那些时间比较短的任务,如果要执行长时间的任务,

最好还是用java.util.concurrent这个包下面提供的类手动来做。

赞助本站

人工智能实验室

相关热词: android开发 教程

AiLab云推荐
展开

热门栏目HotCates

Copyright © 2010-2024 AiLab Team. 人工智能实验室 版权所有    关于我们 | 联系我们 | 广告服务 | 公司动态 | 免责声明 | 隐私条款 | 工作机会 | 展会港