Android-AsyncTask使用与源码解析

2019-05-28  本文已影响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();
        }
    }
上一篇下一篇

猜你喜欢

热点阅读