您的位置:首页 > 移动开发 > Android开发

android AsyncTask分析

2016-12-07 22:37 246 查看
  android为我们提供了AsyncTask类,它能完成异步任务。 它可以在线程池中进行后台任务,然后把结果返回到主线程中进行UI更新,也可以在任务为完成的情况下返回执行进度,更新UI界面的进度显示。

  根据这个类的功能,看起来和上一篇的Handler的使用很类似,没错该类封装了Thread和Handler。官方文档上注释对于长时间的后台任务,不赞同使用该类,推荐使用线程池。

需要注意的点:

AsyncTask的对象必须在主线程创建,execute方法必须在主线程调用。一个AsyncTask对象只能执行一次execute方法。

AsyncTask一般用法:

//第一个参数表示doInBackground()方法的参数类型
//第二个参数表示onProgressUpdate()方法的参数类型
//第三个参数表示doInBackground()方法返回的参数类型
private class DownloadTask extends AsyncTask<Void, Integer, String> {
private String mName;

public DownloadTask(String name) {
super();
mName = name;
}

@Override
protected void onPreExecute() {
super.onPreExecute();
}

@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
}

@Override
protected String doInBackground(Void... params) {
return mName;
}

@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
}


onPreExecute() 方法: 在异步任务开始前调用。

doInBackground() 方法: 调用该方法执行异步任务,在线程池中运行,处理任务时可以调用publishProgress()方法更新进度,publishProgress()方法会调用onProgressUpdate()方法。

onProgressUpdate() 方法: 在主线程中运行。

onPostExecute() 方法: 在主线程中运行,doInBackground() 方法运行完毕之后,并且中途没有取消,那么就会调用onPostExecute() 方法。

onCancelled() 方法: 如果异步任务被取消,就会回调该方法。

  现在分析一下AsyncTask的工作流程代码:

先从构造方法方法开始:

public AsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);

Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
Result result = doInBackground(mParams);
Binder.flushPendingCommands();
return postResult(result);
}
};

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 occurred while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
}
}
};
}


  构造方法内会创建2个实例,当前的mFuture封装了mWorker,mWorker的call()会调用doInBackground()方法,并且最后调用postResult()方法。这2个实例比较重要,这里需要注意一下。

  接下来我们从execute()方法开始分析:

@MainThread
public final AsyncTask<Params, Progress, Result>
execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}


该方法内部调用了executeOnExecutor()方法:

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


在上面代码中可以看到,该方法会先调用onPreExecute()方法,之后调用exec.execute()方法,这里的exec是一个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);
}
}
}


  根据上面的代码,之前调用了exec.execute(mFuture),也就是说调用SerialExecutor的execute()方法,在该方法内调用了mFuture的run()方法,run()方法内部调用了mFuture封装的mWorker的call()方法。如果r.run()方法结束,调用scheduleNext()方法,处理下一个异步任务。

查看mWorker的call()方法:

mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true);

Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
//noinspection unchecked
Result result = doInBackground(mParams);
Binder.flushPendingCommands();
return postResult(result);
}
};


  看到这里就非常明简单了,在这里调用了doInBackground()方法,最后调用postResult()方法,查看postResult方法:

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


  异步任务结束后得到的结果会通过getHandler()获得的Handler处理,查看该Handler的代码:

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


  可以发现,该Handler的Looper为主线程中的Looper,所以当前的消息最后到主线程中进行处理,如果当前消息的what为MESSAGE_POST_RESULT,调用finish()方法,同时传入结果,查看AsyncTask的finish()方法:

private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}


  如果中途没有取消任务,那就会调用onPostExecute()方法,不然调用onCancelled()方法,到这里整个异步任务处理结束。

  看一下AsyncTask工作流程:

Created with Raphaël 2.1.0execute()方法onPreExecute()方法SerialExecutor对象的execute(Runnable r)方法调用上面的r的run()方法,也就是mFuture的run(),其内部调用了mWorker的call()方法mWorker.call()方法doInBackground()方法postResult(result)方法Handler发送消息,之后消息进入主线程Handler中调用AsyncTask.finish(result)方法调用onCancelled()或onPostExecute结束

整个AsyncTask工作流程大致就是这样。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: