The use of AsyncTask and source code analysis

AsyncTask details

Introduction: In the actual development of Android, thread communication is often involved. For example, when we obtain a picture, we first obtain it from the network and then enter the page. For example, network operations need to be performed in background threads, but when displaying Data needs to be sent to the main thread, which involves thread communication. Of course, there are many kinds of thread communication, such as the Handler launched by Google. Of course, the Binde mechanism in common process communication is also possible. Implementing thread communication also provides a more useful class, which is AsyncTask.
This article not only describes the use of AsyncTask, but also analyzes the source code in order to better understand the AsyncTask mechanism.
Before that, you need to understand the following content

Handler:
A class introduced by Google to solve the communication problem between different threads. It is often used in development
ThreadFactory:
thread factory, used to uniformly create a specified thread
AtomicInteger:
used to obtain a class for self-incrementing Integer, you can specify the seed for initialization
AtomicBoolean:
used for To obtain the class of self-incrementing Booleanr, you can specify the seed of initialization
Executor:
the unified implementation interface of the thread pool, in which a thread pool is custom implemented SerialExecutor
Callable: a thread
with a return value, and the commonly used creation methods include directly creating Thread and passing Runnable. method to create Thread, but these two methods have no return value
FutureTask:
this class is used to wrap callable or runnable, used to obtain the execution result asynchronously, and the get()return value can be obtained through the method
ArrayDeque:
the circular queue implemented by the array, the traditional queue is first-in-first-out Out, the queue can obtain data through both ends, this article is very well written, you can take a look at
https://www.cnblogs.com/wxd0108/p/7366234.html

Instructions

The usage method is not very complicated. The commonly used rewriting methods are doInBackground(), onProgressUpdate(), onPostExecute(), onCancelled()which respectively represent the processing of background data, the update of the progress, the result of the completion and the cancellation.

    private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
        protected Long doInBackground(URL... urls) {
            int count = urls.length;
            long totalSize = 0;
            for (int i = 0; i < count; i++) {
                totalSize += Downloader.downloadFile(urls[i]);
                publishProgress((int) ((i / (float) count) * 100));
                // Escape early if cancel() is called
                if (isCancelled()) break;
            }
            return totalSize;
        }

        protected void onProgressUpdate(Integer... progress) {
            setProgressPercent(progress[0]);
        }

        protected void onPostExecute(Long result) {
            showDialog("Downloaded " + result + " bytes");
        }
        //当取消之后调用的方法
        @Override
        protected void onCancelled() {
            super.onCancelled();
        }
    }
        //使用方法
        DownloadFilesTask task = new DownloadFilesTask();
        //消息的发送
        task.execute();
        //消息的取消
        task.cancel(true);

start static code block

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

In the static code fast, a thread pool is mainly created. The maximum thread size of the thread pool is calculated according to the number of cores of the CPU. The maximum value is 4 and the minimum value is 2.

SerialExecutor

When the inner class is finally executed , the method execute()of the class will be calledexecute()

    private static class SerialExecutor implements Executor {
        final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
        Runnable mActive;

        public synchronized void execute(final Runnable r) {
           //插入runnable到队列的尾部
            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);
            }
        }
    }

Construction method

There are three construction methods, but two methods are hidden, but the third one is finally called

    public AsyncTask(@Nullable Looper callbackLooper) {
        //获取一个Handler,该Handler主要是主线程Hnadler,因为有两个构造方法是隐藏的QAQ
        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
                    //回调doInBackground方法,该方法是用户需要手动去实现的方法,获取具体的结果值
                    result = doInBackground(mParams);
                    //线程更新
                    Binder.flushPendingCommands();
                } catch (Throwable tr) {
                    //将当前状态置为取消状态
                    mCancelled.set(true);
                    throw tr;
                } finally {
                    //将获取的结果通过Handler发送出去
                    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);
                }
            }
        };
    }

We can see that the construction method mainly creates two objects, namely WorkerRunnableand FutureTask. These two methods
are mainly for thread management. Corresponding operations are performed according to the values ​​obtained by the thread, such as canceling, sending progress or completing sending results.

postResult(),postResultIfNotInvoked()

When the message is sent, the related message will be processed in the InternalHandler

    private Result postResult(Result result) {
        @SuppressWarnings("unchecked")
        Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
                new AsyncTaskResult<Result>(this, result));
        message.sendToTarget();
        return result;
    }
    private void postResultIfNotInvoked(Result result) {
        final boolean wasTaskInvoked = mTaskInvoked.get();
        if (!wasTaskInvoked) {
            postResult(result);
        }
    }

postResult(),postResultIfNotInvoked()

When the message progress is sent, the related messages will be processed in the InternalHandler, which is actively called by the user, and the callback result is in onProgressUpdate, and the user can display it according to the different progress.

    @WorkerThread
    protected final void publishProgress(Progress... values) {
        if (!isCancelled()) {
            //发送进度消息
            getHandler().obtainMessage(MESSAGE_POST_PROGRESS,
                    new AsyncTaskResult<Progress>(this, values)).sendToTarget();
        }
    }

executeOnExecutor()

When the user calls the execute() method, it will go to this method. Usually, it can only go once, because there is a judgment in it, but if it is called, execute(Runnable runnable)it will not be restricted .

    @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();
        //执行任务,默认的是```SerialExecutor```中的方法,前面介绍过
        mWorker.mParams = params;
        exec.execute(mFuture);

        return this;
    }

Summarize

AsyncTask is a class made by Google to facilitate the communication of different threads. It is suitable for simple thread communication. It can easily transfer messages between UI threads and sub-threads without creating Handlers or redundant threads, but it is not suitable for doing Time-consuming operations If you need time-consuming operations, you can use Executor, ThreadPoolExecutor or FutureTask

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324822396&siteId=291194637