展会信息港展会大全

源码分析Android AsyncTask
来源:互联网   发布日期:2016-01-14 12:40:16   浏览:1831次  

导读:Android UI操作是线程不安全的,若想在子线程红进行UI操作,需要借助Android提供的Handler。Android提供的AsyncTask其实是对Handler的封装,方便我们在子...

Android UI操作是线程不安全的,若想在子线程红进行UI操作,需要借助Android提供的Handler。Android提供的AsyncTask其实是对Handler的封装,方便我们在子线程中更新UI元素。AsyncTask是一个泛型类,书写格式为: AsyncTask。这三个参数的用途如下:

1. Params

这三个参数的用途如下:

1. Params

在执行AsyncTask时需要传入的参数,可用于在后台任务中使用。

2. Progress

后台任务执行时,如果需要在界面上显示当前的进度,则使用这里指定的泛型作为进度单位。

3. Result

当任务执行完毕后,如果需要对结果进行返回,则使用这里指定的泛型作为返回值类型。

Android SDK中给出的一个AsyncTask用法如下:

private class DownloadFilesTask extends AsyncTask(URL, Integer, Long) {

protected Long doInBackground(URL... urls) {

int count = urls.length;

long totalSize = 0;

for (int i = 0; i

AsyncTask是个抽象类,有四个方法需要被重写,这四个方法的的调用过程如下:

第1步. onPreExecute()方法会在后台任务开始执行之间调用,用于进行一些界面上的初始化操作。

第2步. doInBackground(Params...)方法中的所有代码都会在子线程中运行,我们应该在这里去处理所有的耗时任务。任务一旦完成就可以通过return语句来将任务的执行结果进行返回。如果需要更新UI元素,比如说反馈当前任务的执行进度,可以调用publishProgress(Progress...)方法来完成。

第3步. 当在后台任务中调用了publishProgress(Progress...)方法后,onProgressUpdate(Progress...)方法就很快会被调用,方法中携带的参数就是在后台任务中传递过来的。在这个方法中可以对UI进行操作,利用参数中的数值就可以对界面元素进行相应的更新。

第4步. 当后台任务执行完毕并通过return语句进行返回时,onPostExecute(Result)很快会被调用。此处可以

进行UI操作。

AsyncTask的源码

当初使用AsyncTask的时候,一直不明白onProcessUpdate为何会定期被调用。后来在工作中要实现一个定时更新任务进度的功能,我们用的是一个Handler给自己发送消息来进行定时刷新。现在研究了一下AsyncTask的实现原理,发现它也是使用Handler给自己发送消息的原理来实现定时刷新。当我选用的是Android 4.4的源码,若大家能搞懂AsyncTask的实现原理,也能自己写一个简单的AsyncTask。

首先看看构造函数:注意,构造函数一定要在UI中调用。

/**

* Creates a new asynchronous task. This constructor must be invoked on the UI thread.

*/

public AsyncTask() {

mWorker = new WorkerRunnable() {

public Result call() throws Exception {

mTaskInvoked.set(true);

Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);

//noinspection unchecked

return postResult(doInBackground(mParams));

}

};

mFuture = new FutureTask(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());

} catch (CancellationException e) {

postResultIfNotInvoked(null);

}

}

};

}这个函数初试化了两个变量:mWorker和mFuture。mWorker是一个Callable对象,mFuture是一个实现了Runnable和Future的对象。启动AsyncTask调用的是execute(Params)public final AsyncTask execute(Params... params) {

return executeOnExecutor(sDefaultExecutor, params);

}该方法调用了executeOnExecutor()方法,代码如下:

public final AsyncTask 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;

}该方法先设置运行状态,然后调用onPreExecute,最后调用exec.execute(mFuture).传入的exec是sDefaultExecutor, sDefaultExecutor是一个SerialExecutor对象,源代码如下:

private static class SerialExecutor implements Executor {

final ArrayDeque mTasks = new ArrayDeque();

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

}

}

}

当调用sDefaultExecutor.execute(runnable),该方法用一个ArrayDeque来保存runnable,runnable会在合适的时候被调用。第一次运行mActivity等于null了,于是会调用scheduleNext()方法。在这个方法中会从队列的头部取值,并赋值给mActive对象,然后调用THREAD_POOL_EXECUTOR去执行取出的取出的Runnable对象。这里使用了一个try finally代码块,并在finally中调用了scheduleNext()方法,每次当一个任务执行完毕后,下一个任务才会得到执行,SerialExecutor模仿的是单一线程池的效果,如果我们快速地启动了很多任务,同一时刻只会有一个线程正在执行,其余的均处于等待状态。

sDefaultExecutor.execute(Runnable)传入的对象是mFuture,mFuture是一个FutureTask对象,其构造函数如下所示:

public FutureTask(Callable callable) {

if (callable == null)

throw new NullPointerException();

this.callable = callable;

this.state = NEW;// ensure visibility of callable

}由AsyncTask的构造函数可知,FutureTask中的callable是mWorkder对象。FutureTask的run()代码如下所示:public void run() {

if (state != NEW ||

!UNSAFE.compareAndSwapObject(this, runnerOffset,

null, Thread.currentThread()))

return;

try {

Callable c = callable;

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

V result;

boolean ran;

try {

result = c.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);

}

}因此,最终会调用mWorker的call()。mWorker的call()位于AsyncTask的构造函数中,大家可以发现其先调用doInBackgroud(Params),然后调用postResult().postResult(Result)的源代码如下:

private Result postResult(Result result) {

@SuppressWarnings("unchecked")

Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,

new AsyncTaskResult(this, result));

message.sendToTarget();

return result;

}sHandler是一个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;

}

}

}

当传入的是一条MESSAGE_POST_RESULT消息,就会去执行AsyncTask.finish()方法,如果这是一条MESSAGE_POST_PROGRESS消息,就会去执行onProgressUpdate()方法。当我们在doInBackgroud(Params)中利用for循环来调用publishProgress(Progress... values),就会模拟出

定时调用onProgressUpdate(Progress... values)的效果。publishProgress(Progress... values)的源码如下:

protected final void publishProgress(Progress... values) {

if (!isCancelled()) {

sHandler.obtainMessage(MESSAGE_POST_PROGRESS,

new AsyncTaskResult(this, values)).sendToTarget();

}

}

它首先会判断线程是否已经结束,若没结束,则sHandler给自己发送一个消息,消息的类型为MESSAGE_POST_PROGRESS,sHandler.handleMessage(Message)则会调用onProgressUpdate(Progress... values)。

由上可知sDefaultExecutor先调用mFuture的run(), 而mFuture的run()又会调用mWorker的call()。当执行完一个任务后,mFuture的done()会被回调。done()会调用ppostResultIfNotInvoked(Result result),源码如下:

private void postResultIfNotInvoked(Result result) {

final boolean wasTaskInvoked = mTaskInvoked.get();

if (!wasTaskInvoked) {

postResult(result);

}

}postResult(Result)已经在前面有过讲解,在此不再赘述。

赞助本站

人工智能实验室

相关热词: android开发

AiLab云推荐
展开

热门栏目HotCates

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