Introduction

AsyncTaskIt is a simple class provided by the Android platform for performing asynchronous tasks in the background without blocking the main thread to maintain the responsiveness of the user interface. It can be used to handle some time-consuming operations, such as network requests, database queries, etc.

Interestingly, AsyncTaskit’s like a hard-working little assistant that can help you do some heavy work in the background, while you can continue to focus on other things, such as drinking a cup of coffee or playing mobile games.

However, AsyncTaskit has been officially marked as deprecated in the latest version of Android. This is because AsyncTaskof some potential issues and limitations, such as:

  1. Memory Leak : If AsyncTaskis not canceled or completed correctly, it can cause a memory leak because it holds a reference to an external object.
  2. Configuration change issue : When the screen is rotated or the configuration is changed, AsyncTasksaving and restoring the state may not be handled correctly, resulting in data loss or other abnormalities.
  3. Concurrency limit : AsyncTaskBy default, a single background thread is used to execute tasks, which means that only one task can be executed at the same time. In some scenarios, multiple tasks may need to be executed in parallel, and AsyncTaskthis demand cannot be met.

In fact, all the above problems can be solved through code design, but this article is to introduce the “outdated” ones AsyncTask, so I won’t introduce them in too much. Common methods are to onDestroyrelease references in time, or to temporarily save data for subsequent use.

However, thinking too much about exception cases defeats AsyncTaskthe original intention of choosing. Therefore, Android officially recommends other asynchronous task processing methods.

So, although AsyncTaskit was a commonly used tool in developing Android applications in the past, it has now been officially deprecated and developers should prioritize using more modern ways of handling asynchronous tasks.

Source code

The key to thread communication: Handler

Internally AsyncTask, it maintains a static InternalHandlerclass that extends from Handler. This InternalHandleris used to send messages to the main thread in a background thread.

The following is the definition AsyncTaskin the source code InternalHandler:

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

In AsyncTask, when it needs to send a message, it creates an Messageobject and sends it to InternalHandler.

AsyncTaskThere is a method named in the source code for postResult()sending task result messages. Below is postResult()the code snippet of the method

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

By using InternalHandlerand MessageAsyncTaska mechanism for message passing between the background thread and the main thread is implemented. The background thread can send messages to the main thread by calling the postResult()or postProgress()method, and the in the main thread InternalHandlerwill receive these messages and perform corresponding operations, such as calling the onPostExecute()or onProgressUpdate()method to update the UI.

AsyncTaskTwo Executors in

AsyncTaskThere are two Executors, one SERIAL_EXECUTORis a serial execution Executor, which ensures that all tasks are executed in the order in which they are submitted. This is useful for situations where you need to avoid multiple tasks accessing a shared resource at the same time, because it ensures that one task is completed before the next task is executed. The specific code + comments are as follows:

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

The other one is: THREAD_POOL_EXECUTOR, the official explanation is translated and posted below:

An Executor that can be used to execute tasks in parallel.

It has been deprecated that using a single thread pool for different tasks can lead to sub-optimal behavior. Small -CPU-intensive tasks can benefit from a bounded pool and queue, while long-blocking tasks, such as network operations, can benefit from multiple threads. Please use or create an Executor configured to match your usage.

In other words, a serial execution thread pool was previously set up to ensure that tasks can be called in an orderly manner, but the serial blocking is too strong, so a parallel thread pool is added to speed up the thread’s work efficiency. .

public static final Executor THREAD_POOL_EXECUTOR;

static {
    ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
            CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
            new SynchronousQueue<Runnable>(), sThreadFactory);
    threadPoolExecutor.setRejectedExecutionHandler(sRunOnSerialPolicy);
    THREAD_POOL_EXECUTOR = threadPoolExecutor;
}

It is used here SynchronousQueueas a task queue, which can quickly respond to tasks in a one-to-one producer-consumer format.

Leave a Reply

Your email address will not be published. Required fields are marked *