AsyncTask的初次探索

AsyncTask

概述

AsyncTask 是一种轻量级的异步任务类,它可以在线程池中执行后台任务,然后把执行的进度和最终结果传递给主线程并在主线程中更新UI。

核心方法
  1. onPreExecute():在主线程中执行,在异步任务执行之前,此方法会被调用,一般可以用于做一些准备工作。
  2. doInBackground(Params…params):在线程池中执行,此方法用于执行异步任务,params参数表示异步任务的输入参数。在此方法中可以通过publishProgress方法来更新任务的进度,publishProgress方法会调用onProgressUpdate方法。另外此方法需要返回计算结果给onPostExecute方法。
  3. onProgressUpdate(Progress…values):在主线程中执行,当后台任务的执行进度发生改变时此方法会被调用。
  4. onPostExecuter(Result result):在主线程中执行,在异步任务执行之后,此方法会被调用,其中result参数是后台任务的返回值,即doInBackground的返回值。
注意事项
  1. AsyncTask 的对象必须在主线程中创建。
  2. execute方法必须在UI线程调用。
  3. 不能在程序中直接调用onPreExecute、doInBackground、onProgressUpdate、onPostExecuter方法。
  4. 一个AsyncTask对象只能执行一次,即只能调用一次execute方法,否则会报运行时异常。
使用示例
public class DownloadAsyncTask extends AsyncTask<URL, Integer, Boolean> {
    private static final String TAG = "DownloadAsyncTask";

    @Override
    protected Boolean doInBackground(URL... urls) {
        // 根据传进来的url下载文件
        ......
        // 更新下载进度
        publishProgress(50);
        // 返回下载结果
        if (isCancelled()) {
            return false;
        }
        return true;
    }

    @Override
    protected void onProgressUpdate(Integer... progress) {
        // 下载进度更新
        Log.d(TAG, "progress: " + progress[0].toString());
    }

    @Override
    protected void onPostExecute(Boolean isSuccessful) {
        // 下载成功与否
        if (isSuccessful) {
            Log.d(TAG, "download success");
        } else {
            Log.d(TAG, "download fail");
        }
    }
}

// 调用
new DownloadAsyncTask().execute(url);
补充
  1. onCancelled():在主线程中执行,当异步任务被取消时,onCancelled()方法会被调用,这个时候onPostExecuter则不会被调用。
  2. execute()与executeOnExecutor()
    • 在Android 1.6之前,AsyncTask是串行执行任务的。
    • Android 1.6的时候,AsyncTask开始采用线程池处理并行任务。
    • 从Android 3.0开始,为了避免AsyncTask所带来的并发错误,AsyncTask又采用一个线程来串行执行任务。
    • 在Android 3.0以及后续版本中,可以通过AsyncTask的executeOnExecutor方法来并行地执行任务。
工作原理
  1. AsyncTask的继承关系

     ......
    // 先看继承关系,AsyncTask并没有继承什么基类
    public abstract class AsyncTask<Params, Progress, Result> {
        ......
    }
    
  2. 从构造方法入手

    ......
    public abstract class AsyncTask<Params, Progress, Result> {
    	......
        // 供外部调用的只有下面这个
        public AsyncTask() {
            this((Looper) null);
        }
    
        /**
         * @hide
         */
        public AsyncTask(@Nullable Handler handler) {
            this(handler != null ? handler.getLooper() : null);
        }
    
        /**
         * @hide
         */
        public AsyncTask(@Nullable Looper callbackLooper) {
            // 构造方法最终调用的构造方法,先是拿到了一个内部的handler
            mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
                ? getMainHandler()
                : new Handler(callbackLooper);
            
    		// 一个Callable
            mWorker = new WorkerRunnable<Params, Result>() {
                ......
            };
    		// 一个FutureTask,传参是刚才的那个Callable
            mFuture = new FutureTask<Result>(mWorker) {
                ......
            };
        }
    
        ......
    }
    
  3. 再看execute()方法

    ......
    public abstract class AsyncTask<Params, Progress, Result> {    
    	......
    	// 外部调用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;
            // 线程池任务,传入构造方法中初始化的一个FutureTask
            exec.execute(mFuture);
    
            return this;
        }
        
        @MainThread
        public static void execute(Runnable runnable) {
            sDefaultExecutor.execute(runnable);
        }
        ......
    }
    
  4. 从上步看来最后都走的sDefaultExecutor.execute(),所以先来看一下sDefaultExecutor

    ......
    public abstract class AsyncTask<Params, Progress, Result> {
    	......
    	public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
    	......
    	private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
        ......
        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);
                }
            }
        }
        ......
    }
    
    
  5. 回到第三步提交线程池任务的时候,传参是mFuture,所以再回过头去看mWorker、mFuture

    ......
    public abstract class AsyncTask<Params, Progress, Result> {
    	......
        public AsyncTask(@Nullable Looper callbackLooper) {
            ......
    		mWorker = new WorkerRunnable<Params, Result>() {
                // 相当于run方法里执行的任务,call方法会在线程池中执行
                public Result call() throws Exception {
                    mTaskInvoked.set(true);
                    Result result = null;
                    try {
                        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                        //noinspection unchecked
                        // 执行异步任务
                        result = doInBackground(mParams);
                        Binder.flushPendingCommands();
                    } catch (Throwable tr) {
                        mCancelled.set(true);
                        throw tr;
                    } finally {
                        postResult(result);
                    }
                    return 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);
                    }
                }
            };
        }
    
        ......
    }
    
  6. 最后看一下任务执行完毕后的结果,主要是postResultIfNotInvoked()和postResult()方法

    ......
    public abstract class AsyncTask<Params, Progress, Result> {
        ......
        private void postResultIfNotInvoked(Result result) {
            final boolean wasTaskInvoked = mTaskInvoked.get();
            if (!wasTaskInvoked) {
                postResult(result);
            }
        }
        
    	private Result postResult(Result result) {
            @SuppressWarnings("unchecked")
            // 发消息MESSAGE_POST_RESULT通知,handler默认为一个内部的handler:InternalHandler
            Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
                    new AsyncTaskResult<Result>(this, result));
            message.sendToTarget();
            return result;
        }
        ......
    	private void finish(Result result) {
            if (isCancelled()) {
                onCancelled(result);
            } else {
                // 在主线程处理结果
                onPostExecute(result);
            }
            // 任务完成
            mStatus = Status.FINISHED;
        }
        
    	private static class InternalHandler extends Handler {
            public InternalHandler(Looper looper) {
                super(looper);
            }
    
            @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
            @Override
            public void handleMessage(Message msg) {
                AsyncTaskResult<?> result = (AsyncTaskResult<?>) msg.obj;
                switch (msg.what) {
                    case MESSAGE_POST_RESULT:
                        // 调用 finish
                        result.mTask.finish(result.mData[0]);
                        break;
                    case MESSAGE_POST_PROGRESS:
                        // 调用进度更新
                        result.mTask.onProgressUpdate(result.mData);
                        break;
                }
            }
        }
        ......
    }
    
参考

[1] 任玉刚.Android开发艺术探索[M].电子工业出版社,2015:507.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值