AsyncTask 原理解析

首先 我们知道AsyncTask 是封装了线程池和Handler ,那就写一个简单的例子开始说起,

class  MyAsyncTask extends AsyncTask<String, Void, String>{
        String str;

        public MyAsyncTask(String str){
            this.str = str;
        }

        public MyAsyncTask(){
        }

        @Override
        protected String doInBackground(String... strings) {
            Log.d(TAG, "doInBackground: " + strings[0]);
            return strings[0];
        }


        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            Log.d(TAG, "onPostExecute: " + s);
        }
    }

使用方式 :

new MyAsyncTask().execute("sjh");

这样就使用了AsyncTask ,从 execute()方法说起,点击该方法,看到:

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

点击exectueOnExecutor方法,可以到

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

先判断线程状态,在类中寻找一下相应的状态定义,发现:

/**
     * Indicates the current status of the task. Each status will be set only once
     * during the lifetime of a task.
     */
    public enum Status {
        /**
         * Indicates that the task has not been executed yet.
         */
        PENDING,
        /**
         * Indicates that the task is running.
         */
        RUNNING,
        /**
         * Indicates that {@link AsyncTask#onPostExecute} has finished.
         */
        FINISHED,
    }

这是一个内部枚举类定义任务的状态,并且每个状态只会赋值一次,我们知道一个AsyncTask 创建之后只能用一次,在用就会报错,原因可以结合以上分析得到原因。

再来看看这个 sDefaultExecutor 参数,这是一个串行的线程池,

private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;

 /**
     * An {@link Executor} that executes tasks one at a time in serial
     * order.  This serialization is global to a particular process.
     */
    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);
            }
        }
    }

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

从以上代码知道这是一个Executor, 在 executeOnExecutor方法中,把params赋值给workers,并执行 exec.execute(mFuture); 在看看mFuture 是什么?

executeOnExecutor 中 mFuture 实现了Runnable接口,并且在AsyncTask的构造方法里 对mFuture作了初始化工作:

  /**
     * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
     */
    public AsyncTask() {
        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);
                }
            }
        };
    }

从代码中知道 mFuture 的初始化需要mWorker 对象,并且也对mWorker 作了初始化,另外 也知道mWorker是一个实现了Callable接口的内部类,在其run()方法中 执行了

result = doInBackground(mParams);

由于doInBackground方法是抽象方法,子类必须实现,所以我们在使用的时候就一定要实现此方法并在这里做耗时任务,之后并把结果调用了post方法,

postResult(result);

看看这个postResult()及相关方法源代码:

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


    private static Handler getHandler() {
        synchronized (AsyncTask.class) {
            if (sHandler == null) {
                sHandler = new InternalHandler();
            }
            return sHandler;
        }
    }

    private static class InternalHandler extends Handler {
        public InternalHandler() {
            super(Looper.getMainLooper());
        }

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

    //  result.mTask.finish(result.mData[0]);
    private void finish(Result result) {
        if (isCancelled()) {
            onCancelled(result);
        } else {
            onPostExecute(result);
        }
        mStatus = Status.FINISHED;
    }

显然一目了然,知道这是用handler把结果发送出去。知道这个Handler 是一个内部类 InteralHandler ,然后看到 其构造方法,知道这个Handler用的是主线程的looper,所以这个handler 是在主线程处理消息,再看看熟悉的HandleMessage(Msg),一切都是那么熟悉和清晰。(针对这里不明白为什么要用MainLooper的情况可以参考 Handler机制 )

再次回顾整个流程:

从Exector.execte(Runnable)方法说起,Exector 是里面一个串行 SerialExecutor  对象包含的  THREAD_POOL_EXECUTOR 执行线程池,然后Runable的来源就是在构建AsyncTask的时候初始化的mWorker 和mFuture 对象,mWorker 代表了子线程要执行的任务doInbackground 和 把结果向外抛,利用InternalHandler 对象进行线程切换。

使用:

针对前面的例子,可以

new MyAsyncTask().execute("sjh")

也可以 new MyAsyncTask(“sjh”).execute(); 看到这两种方式,你要明白其不同含义,第一种写法是传入了 params,后面一种写法通过构造函数去传递值,相当于params 为空,没有进行传值,这时候在doInbackground用params 的时候就要注意 params是否有值,我这样写的话用第二种方式会产生异常的,即数组越界。

猜你喜欢

转载自blog.csdn.net/sjh_389510506/article/details/88713440
今日推荐