美文网首页
Android AsyncTask 机制

Android AsyncTask 机制

作者: 呦你别闹 | 来源:发表于2019-06-16 13:20 被阅读0次

在Android中,为我们提供了两种异步操作机制,一种是Handler另一种就是AsyncTask了。
如何使用AsyncTask?
自定义类继承AsyncTask,必须重写doInBackground方法,然后可以根据需求重写onPreExecute、onPostExecute、onProgressUpdate、onCancelled等方法。
然后调用execute方法去执行。
接下来我们就从execute这个方法,去看看AsyncTask 是怎样的一个流程。

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

我们可以看到在execute方法中调用了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);
            }
        }
    }

通过这里我们就知道了sDefaultExecutor也就相当于SerialExecutor 的实例对象,
接下来看看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;
    }

这个方法首先判断了当前的执行状态,意思也就是每个AsyncTask的execute方法只能调用一次。然后调用了一下onPreExecute方法,这个方法是一个空实现的方法是,目的就是我们在使用AsyncTask重写这个方法,去做一些开始前的准备工作。然后把params赋值给mWorker的mParams 。mWorker是一个实现了Callable接口的类。然后就调用了sDefaultExecutor的execute方法,传入了mFuture,mFuture是FutureTask对象,方便用于之后得到处理的结果。回到上面看看execute方法,添加一个Runnable到ArrayDeque的最后,ArrayDeque是一个串行的队列。
然后调用了scheduleNext方法,这个方法调用了THREAD_POOL_EXECUTOR的execute方法,把ArrayDeque的第一个线程对象去处理。到这里我们也知道了,AsyncTask是一个串行的机制。

//cpu数量
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();

//核心线程的数量 2-4
 private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));

//非核心线程的数量
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;

//非核心线程的存活时间,单位:秒
 private static final int KEEP_ALIVE_SECONDS = 30;

//线程池的线程工厂类
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>(128);

//线程池对象
    public static final Executor THREAD_POOL_EXECUTOR;

    static {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
                sPoolWorkQueue, sThreadFactory);
        threadPoolExecutor.allowCoreThreadTimeOut(true);
        THREAD_POOL_EXECUTOR = threadPoolExecutor;
    }

THREAD_POOL_EXECUTOR其实就是一个线程池对象,执行的线程也就是我们的mFuture里面的mWorker这个线程。要执行一个线程肯定要执行run方法,看看它的run方法做了一些什么。

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

先是调用call方法得到结果,在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;
            }
        };
  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);
                }
            }
        };
  private Result postResult(Result result) {
        @SuppressWarnings("unchecked")
        Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
                new AsyncTaskResult<Result>(this, result));
        message.sendToTarget();
        return result;
    }

mFuture初始化实在构造方法中,当工作线程执行完毕,就会调用done方法,通过postResultIfNotInvoked判断是否将消息返回了,如果没有返回将消息返回。

private void postResultIfNotInvoked(Result result) {
        final boolean wasTaskInvoked = mTaskInvoked.get();
        if (!wasTaskInvoked) {
            postResult(result);
        }
    }

下面看看内部的Handler,在构造方法中的初始化

 mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper()
            ? getMainHandler()
            : new Handler(callbackLooper);

使用当前的现成的Looper对象构造Handler,如果传入的Looper对象为为空,或者是主线程的Looper会使用内部的InternalHandler 对象,如果其他线程的Handler需自己实现handleMessage方法。

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

里面MESSAGE_POST_RESULT类型就是消息处理完成返回的结果,只能调用一次,而MESSAGE_POST_PROGRESS是当前的进度,通过publishProgress方法调用。

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

到这里AsyncTask的基本流程已经完成。

总结:
在构造方法中,初始化Handler对象,工作线程(Callable),和FutureTask(用于获取线程的返回结果)。通过调用execute方法,将任务加入一个串行队列中进行排队,然后交给线程池去处理任务,得到返回结果通过Handler完成线程的调度。

相关文章

网友评论

      本文标题:Android AsyncTask 机制

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