AsyncTask异步消息处理机制
来源:互联网 发布:淘宝摄影发展趋势 编辑:程序博客网 时间:2024/03/28 22:23
AsyncTask<Params,Progress,Result>是一个抽象类,使用时必须创建一个子类继承它
其中,Parmas:启动任务执行的输入参数的类型,可用于后台任务中使用;
Progress:后台任务执行时,若需要在界面上显示进度,则使用这里指定的泛型作为进度单位;
Result:后台任务执行完成后返回的结果的类型。
启动方法:new Task().execute();
需要重写的方法:
onPreExecute():在执行后台任务之前被调用,用于完成一些初始化操作,比如显示一个进度条对话框。
doInBackground(Params...):这个方法的所有代码都会在子线程中运行,所以此方法不可以进行UI操作,用于执行耗时操作,如下载。可以调用publishProgress(Progress... values)反馈当前任务的执行进度。注意:此方法不可以进行UI操作。
onProgressUpdate(Progress... values):当在后台调用publishProgress(Progress... values)方法之后,此方法就会被调用。用于进行UI操作,如更新进度条的进度。
onPostExecute(Result result):当后台任务完成,即doInBackground(Params...)完成并通过return语句返回,此方法会被调用。用于利用返回的数据进行一些UI操作,如关闭进度对话框和提醒任务执行的结果。
注意:必须在UI线程创建AsyncTask实例和调用execute();每个AsyncTask只能被调用一次。
源码解析
下面进行源码分析:从我们的执行异步任务的起点开始,进入execute方法:
- 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:"
- + " 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;
- }
20行:执行了onPreExecute(),当前依然在UI线程,所以我们可以在其中做一些准备工作。
22行:将我们传入的参数赋值给了mWorker.mParams
23行:exec.execute(mFuture)
相信大家对22行出现的mWorker,以及23行出现的mFuture都会有些困惑。
mWorker找到这个类:
- private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
- Params[] mParams;
- }
- 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));
- }
- };
- //….
- }
- private Result postResult(Result result) {
- @SuppressWarnings("unchecked")
- Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
- new AsyncTaskResult<Result>(this, result));
- message.sendToTarget();
- return result;
- }
- private static class AsyncTaskResult<Data> {
- final AsyncTask mTask;
- final Data[] mData;
- AsyncTaskResult(AsyncTask task, Data... data) {
- mTask = task;
- mData = data;
- }
- }
看到这,我相信大家肯定会想到,在某处肯定存在一个sHandler,且复写了其handleMessage方法等待消息的传入,以及消息的处理。
- 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;
- }
- }
- }
- private void finish(Result result) {
- if (isCancelled()) {
- onCancelled(result);
- } else {
- onPostExecute(result);
- }
- mStatus = Status.FINISHED;
- }
最后将状态置为FINISHED(excuteOnExecutor)。
mWoker看完了,应该到我们的mFuture了,依然实在构造方法中完成mFuture的初始化,将mWorker作为参数,复写了其done方法。
- public AsyncTask() {
- ...
- 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());
- } catch (CancellationException e) {
- postResultIfNotInvoked(null);
- }
- }
- };
- }
- private void postResultIfNotInvoked(Result result) {
- final boolean wasTaskInvoked = mTaskInvoked.get();
- if (!wasTaskInvoked) {
- postResult(result);
- }
- }
好了,到了这里,已经介绍完了execute方法中出现了mWorker和mFurture,不过这里一直是初始化这两个对象的代码,并没有真正的执行。下面我们看真正调用执行的地方。
execute方法中的:
还记得上面的execute中的23行:exec.execute(mFuture)
exec为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 {
- 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);
- }
- }
- }
16-17行:判断当前mActive是否为空,为空则调用scheduleNext方法
20行:scheduleNext,则直接取出任务队列中的队首任务,如果不为null则传入THREAD_POOL_EXECUTOR进行执行。
下面看THREAD_POOL_EXECUTOR为何方神圣:
- public static final Executor THREAD_POOL_EXECUTOR
- =new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
- TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
- private static final int CORE_POOL_SIZE = 5;
- private static final int MAXIMUM_POOL_SIZE = 128;
- private static final int KEEP_ALIVE = 1;
- 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());
- }
- };
- private static final BlockingQueue<Runnable> sPoolWorkQueue =
- new LinkedBlockingQueue<Runnable>(10);
其实不是这样的,我们再仔细看一下代码,回顾一下sDefaultExecutor,真正在execute()中调用的为sDefaultExecutor.execute:
- 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);
- }
- }
- }
4、总结
到此源码解释完毕,由于代码跨度比较大,我们再回顾一下:
- 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:"
- + " 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;
- }
20行:执行了onPreExecute(),当前依然在UI线程,所以我们可以在其中做一些准备工作。
22行:将我们传入的参数赋值给了mWorker.mParams ,mWorker为一个Callable的子类,且在内部的call()方法中,调用了doInBackground(mParams),然后得到的返回值作为postResult的参数进行执行;postResult中通过sHandler发送消息,最终sHandler的handleMessage中完成onPostExecute的调用。
23行:exec.execute(mFuture),mFuture为真正的执行任务的单元,将mWorker进行封装,然后由sDefaultExecutor交给线程池进行执行。
5、publishProgress
说了这么多,我们好像忘了一个方法:publishProgress
- protected final void publishProgress(Progress... values) {
- if (!isCancelled()) {
- sHandler.obtainMessage(MESSAGE_POST_PROGRESS,
- new AsyncTaskResult<Progress>(this, values)).sendToTarget();
- }
- }
- 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;
- }
- }
- }
6、AsyncTask曾经缺陷
记得以前有个面试题经常会问道:AsyncTask运行的原理是什么?有什么缺陷?
以前对于缺陷的答案可能是:AsyncTask在并发执行多个任务时发生异常。其实还是存在的,在3.0以前的系统中还是会以支持多线程并发的方式执行,支持并发数也是我们上面所计算的128,阻塞队列可以存放10个;也就是同时执行138个任务是没有问题的;而超过138会马上出现java.util.concurrent.RejectedExecutionException;
而在在3.0以上包括3.0的系统中会为单线程执行(即我们上面代码的分析);
空说无凭:下面看测试代码:
- package com.example.zhy_asynctask_demo01;
- import android.app.Activity;
- import android.app.ProgressDialog;
- import android.os.AsyncTask;
- import android.os.Bundle;
- import android.util.Log;
- import android.widget.TextView;
- public class MainActivity extends Activity
- {
- private static final String TAG = "MainActivity";
- private ProgressDialog mDialog;
- private TextView mTextView;
- @Override
- protected void onCreate(Bundle savedInstanceState)
- {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- mTextView = (TextView) findViewById(R.id.id_tv);
- mDialog = new ProgressDialog(this);
- mDialog.setMax(100);
- mDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
- mDialog.setCancelable(false);
- for(int i = 1 ;i <= 138 ; i++)
- {
- new MyAsyncTask2().execute();
- }
- //new MyAsyncTask().execute();
- }
- private class MyAsyncTask2 extends AsyncTask<Void,Void, Void>
- {
- @Override
- protected Void doInBackground(Void... params)
- {
- try
- {
- Log.e(TAG, Thread.currentThread().getName());
- Thread.sleep(10000);
- } catch (InterruptedException e)
- {
- e.printStackTrace();
- }
- return null;
- }
- }
- }
输出结果为:
AsyncTask#1 - AsyncTask #128同时输出
然后10s后,另外10个任务输出。
可以分析结果,得到结论:AsyncTask在2.2的系统中同时支持128个任务并发,至少支持10个任务等待;
下面将138个任务,改成139个任务:
- for(int i = 1 ;i <= 139 ; i++)
- {
- new MyAsyncTask2().execute();
- }
简单说一下出现异常的原因:现在是139个任务,几乎同时提交,线程池支持128个的并发,然后阻塞队列数量为10,此时当第11个任务提交的时候则会发生异常。
简单看一下源码:
- public static final Executor THREAD_POOL_EXECUTOR
- = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
- if (isRunning(c) && workQueue.offer(command)) {
- int recheck = ctl.get();
- if (! isRunning(recheck) && remove(command))
- reject(command);
- else if (workerCountOf(recheck) == 0)
- addWorker(null, false);
- }
- else if (!addWorker(command, false))
- reject(command);
- private boolean addWorker(Runnable firstTask, boolean core) {
- …
- int wc = workerCountOf(c);
- if (wc >= CAPACITY ||
- wc >= (core ? corePoolSize : maximumPoolSize))
- return false;
- …
- }
上面就是使用2.2模拟器测试的结果;
下面将系统改为4.1.1,也就是我的测试机小米2s
把线程数改为139甚至1000,你可以看到任务一个接一个的在那缓慢的执行,不会抛什么异常,不过线程倒是1个1个的在那执行;
好了,如果现在大家去面试,被问到AsyncTask的缺陷,可以分为两个部分说,在3.0以前,最大支持128个线程的并发,10个任务的等待。在3.0以后,无论有多少任务,都会在其内部单线程执行;
至此,AsyncTask源码分析完毕,相信大家对AsyncTask有了更深的理解~~~
- AsyncTask异步消息处理机制
- AsyncTask 异步消息处理机制
- 异步消息处理机制-Handler、AsyncTask
- Android AsyncTask异步处理消息机制
- AsyncTask(异步消息处理机制)
- Android笔记----AsyncTask异步消息处理机制
- AsyncTask异步处理机制
- android os;异步消息处理机制:AsyncTask和Handler
- Android异步消息处理机制(3)AsyncTask基本使用
- Android异步消息处理机制(4)AsyncTask源码解析
- Android多线程,异步消息处理机制, Thread, AsyncTask 简单总结
- 安卓开发:AsyncTask异步消息处理机制使用
- 异步消息处理机制及AsyncTask的使用
- 异步消息与AsyncTask机制
- 异步消息处理机制
- 异步消息处理机制
- 异步消息处理机制
- 异步消息处理机制
- 如何在WordPress页面输出指定的调试信息
- Java迭代法求所有八皇后问题的解
- C- 函数与指针
- 九度OJ 1336:液晶屏裁剪 (GCD)
- C-指针数组与数组指针
- AsyncTask异步消息处理机制
- Linux中修改环境变量及生效方法(永久、临时)环境变量查看
- Struts2系统学习(16)OGNL表达式及基本原理分析
- hdoj 5500Reorder the Books【规律】
- Android学习之路
- C-复杂的声明的阅读
- 15、泛型
- hdu5558 Alice's Classified Message
- 幻 一