美文网首页
Android-AsyncTask使用与源码解析

Android-AsyncTask使用与源码解析

作者: 九号锅炉 | 来源:发表于2019-05-28 14:51 被阅读0次

    AsyncTask使用

    AsyncTask是一个抽象类,使用时需要创建子类继承。其类声明如下:
    public abstract class AsyncTask<Params, Progress, Result>
    继承时需要指定三个泛型参数:
    Params:开始执行任务时需要传入的参数类型
    Progress:用于显示当前任务执行进度
    Result:任务执行结束后的返回结果。
    下面是AsyncTask的一个基本使用:

    class DownloadTask extends AsyncTask<Void, Integer, Boolean> {  
        //任务开始执行之前调用,一般用于界面初始化。
        @Override  
        protected void onPreExecute() {  
        }  
        //在子线程中执行耗时操作
        @Override  
        protected Boolean doInBackground(Void... params) {  
            try {  
                while (true) {  
                    int downloadPercent = doDownload();  
                    publishProgress(downloadPercent);  
                    if (downloadPercent >= 100) {  
                        break;  
                    }  
                }  
            } catch (Exception e) {  
                return false;  
            }  
            return true;  
        }  
      //在后台任务中调用publishProgress之后,这个函数就会被调用,一般用来更新界面。
        @Override  
        protected void onProgressUpdate(Integer... values) {  
            progressDialog.setMessage("当前下载进度:" + values[0] + "%");  
        }  
    //任务结束时调用
        @Override  
        protected void onPostExecute(Boolean result) {  
            progressDialog.dismiss();  
            if (result) {  
                Toast.makeText(context, "下载成功", Toast.LENGTH_SHORT).show();  
            } else {  
                Toast.makeText(context, "下载失败", Toast.LENGTH_SHORT).show();  
            }  
        }  
    }
    

    AsyncTask的使用十分简洁明了,但是底层是怎么实现的?这就需要结合源码来分析了。

    AsyncTask源码解析

    AsyncTask通常调用new DownloadTask().execute()开始执行任务。那么我们就从这里开始研究。首先是构造函数。构造函数首先初始化了一个Handler对象。接着初始化了一个mWorker,然后将mWorker作为参数初始化了mFuture。虽然初始化了两个参数,但是并没有开始执行操作,至于这两个对象的作用是什么需要进一步分析。

    public AsyncTask() {
            this((Looper) null);
        }
    
    public AsyncTask(@Nullable Handler handler) {
            this(handler != null ? handler.getLooper() : null);
        }
    
    public AsyncTask(@Nullable Looper callbackLooper) {
            mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
                ? getMainHandler()
                : new Handler(callbackLooper);
    
            mWorker = new WorkerRunnable<Params, Result>() {
                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);
                    }
                }
            };
        }
    

    接着看execute函数,调用了executeOnExecutor函数,传进sDefaultExecutor作为参数。

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

    在executeOnExecutor会先对状态进行判断,因此如果多次调用execute就会抛出异常。接着就是调用onPreExecute(),在这里可以进行界面的初始化工作。接着调用传入的sDefaultExecutor.execute,而sDefaultExecutor是SerialExecutor,因此需要到SerialExecutor看具体做了什么。

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

    sDefaultExecutor是个SerialExecutor的静态对象。在SerialExecutor中持有一个ArrayDeque,这是一个双端队列,可以从首尾操作元素。在execute中将一个Runnable对象添加到队尾。第一次加载前mActive=null,因此会调用scheduleNext(),scheduleNext()会从ArrayDeque队首取出任务,并使用THREAD_POOL_EXECUTOR.execute进行执行,THREAD_POOL_EXECUTOR其实就是一个线程池。最终执行的是之前添加到队列中的那个Runnable,在这个Runnable的run中会调用mFuture.run.

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

    而mFuture是个FutureTask,再来看FutureTask.run.这里吗调用了Callable.call();而这个Callable就是在构造函数中传进去的mWorker.

        public void run() {
            if (state != NEW ||
                !U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
                return;
            try {
                Callable<V> 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做了什么。在这里终于看到了doInBackground,接着调用postResult

     mWorker = new WorkerRunnable<Params, Result>() {
                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;
                }
            };
    

    postResult中通过Handler发送MESSAGE_POST_RESULT消息。

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

    这样在handleMessage中就会进入MESSAGE_POST_RESULT的case,调用finish

        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:
                        // There is only one result
                        result.mTask.finish(result.mData[0]);
                        break;
                    case MESSAGE_POST_PROGRESS:
                        result.mTask.onProgressUpdate(result.mData);
                        break;
                }
            }
        }
    

    在finish中如果没有被取消,则调用onPostExecute。

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

    而当调用publishProgress,同样会发送MESSAGE_POST_PROGRESS的消息,最终会调用
    onProgressUpdate。

        protected final void publishProgress(Progress... values) {
            if (!isCancelled()) {
                getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
                        new AsyncTaskResult<Progress>(this, values)).sendToTarget();
            }
        }
    

    相关文章

      网友评论

          本文标题:Android-AsyncTask使用与源码解析

          本文链接:https://www.haomeiwen.com/subject/yjxktctx.html