Finish work, daily touch fish ~

An Android development communication group 99+, click open to see the discussion:

Roar! AsyncTask: AsyncTask: AsyncTask: AsyncTask: AsyncTask: AsyncTask: AsyncTask: AsyncTask

AsyncTask is a very old-fashioned thing for many older Android systems. It is a must for job interviews after graduation.

With the advent of EventBus, RxJava, Kotlin coroutines, etc., it has gradually faded from our view, and is probably unheard of by many new Android developers. Can’t help but sigh…

Error, 2333, exclamation: the iteration of technology is so fast, can’t learn…

It is used in some old projects, but it is also used in some old projects. In this section, we will learn why it is discarded and how it is implemented


0x1 Deprecated cause

AsyncTask, introduced by Android(API 3), is a lightweight asynchronous task library that allows operations to be performed in a non-thread-blocking manner. It has been tweaked in several versions:

  • Before Android 1.6, serial execution, principle: a child thread for the serial execution of tasks;
  • Android 1.6 to 2.3, parallel execution, principle: a thread pool with 5 threads is executed in parallel, but if the execution time of the first five tasks is too long, the subsequent task execution will be blocked, so it is not suitable for concurrent execution of a large number of tasks.
  • Android 3.0, serial execution, principle: global thread pool for serial processing tasks;

The official AsyncTask file opens with a line of orange:

The AsyncTask class was deprecated in Android 11(API 30) and is recommended to use java.util.concurrent or Kotlin coroutines instead.

em… It was abandoned. Here’s why:

General meaning:

  • The purpose of AsyncTask is to make the USE of UI threads simple and correct, but the most common use of AsyncTask is to integrate into the UI, which causes problems such as Context leaks, forgotten callbacks, and configuration changes crashing.
  • Compatibility of different versions of AsyncTask;
  • Swallows the exception from doInBackground;
  • Does not provide more functionality than using Executor directly;
  • Helper classes for Thread and Handler, which are not Thread frameworks and are used to perform asynchronous tasks that do not take very long;
  • Complex usage, three general parameters (Params, Progress, Result) + four callback methods;

Description of AsyncTask

Talk is cheap, show you the Code.

    // Inherits the AsyncTask abstract class. It is recommended to declare it as a static inner class of the Activity to avoid context leakage
    // The generic parameters are:
    // 
    // Params → type of parameter passed to start asynchronous task → execute(Params)
    // Progress → Asynchronous task execution process, return the Progress value
    // Result → Result type → doInBackground()
    // 
    class MyAsyncTask: AsyncTask<Task, Int, String>() {

        // Must be rewritten! A time-consuming operation is performed and the result is displayed
        override fun doInBackground(vararg params: Task?).: String { return "Performing time-consuming operations" }

        // This callback is automatically called before executing execute(). This callback is used for interface initialization
        override fun onPreExecute(a){}// Display the progress of task execution in main thread, automatic call, rewrite as needed
        override fun onProgressUpdate(vararg values: Int?).{}// Accept the result of thread task execution, which is automatically called when the thread task finishes, where the result can be updated to the UI component
        override fun onPostExecute(result: String?).{}Async: async: async: async: async: async: async: async: async: async: async: async: async
        // This method calls onPostExecute and will not be called
        override fun onCancelled(a){}}Execute (XXX) after initializing a custom AsyncTask instance in the main thread
    Execute () can only be called once per AsyncTask instance, and multiple calls will throw an exception
    
    // Note ① : The Activity is rebuilt (such as screen rotation), the previously held Activity reference is invalid, and the task is running normally.
    // However, after the task is executed, modifying the UI in onPostExecute does not take effect. You are advised to resume the Activity in related methods
    // restart AsyncTask;
    
    Asynctask.cancle () is the best way to set AsyncTask in onDestory() of your Activity or Fragment
    Canceled status is canceled, and check whether the status of AsyncTask is canceled in doInBackground:
    // asynctask.status. RUNNING, if yes, the task is returned
}
Copy the code

em… Usage looks, also not very complex, then we come to understand the principle behind (source)~

0x3, Close read source code

AsyncTask: AsyncTask: AsyncTask: AsyncTask: AsyncTask: AsyncTask: AsyncTask: AsyncTask: AsyncTask: AsyncTask: AsyncTask

  • How do asyncTasks use a global thread pool for serial execution? What is the thread pool parameter configuration?
  • ② How are asynchronous tasks designed? What are the flow states? How to handle multiple asynchronous tasks? Is it useful to queue? Or some other data structure?
  • ③ When are the related callback methods called? How do I update the UI in a non-UI thread?

(1) the thread pool

THREAD_POOL_EXECUTOR = THREAD_POOL_EXECUTOR = SERIAL_EXECUTOR = THREAD_POOL_EXECUTOR

The THREAD_POOL_EXECUTOR rule initializes a thread pool with a blocked queue of up to 128, followed by another thread pool initializer:

A Runnable queue that automatically fetches tasks from this queue after initialization and after a task has finished and executes them through the THREAD_POOL_EXECUTOR thread pool, enabling serial execution (synchronous locking).

AsyncTask also supports parallel execution:

Call executeOnExecutor(THREAD_POOL_EXECUTOR) and use THREAD_POOL_EXECUTOR instead of SerialExecutor

② Asynchronous task

Execute () → Execute () → executeOnExecutor

Follow the mWorker and mFuture above to where they are initialized → constructor, first mWorker:

Implements the Callable interface, defines the property mParams, instantiates and overwrites the **call()** method, completes thread-specific Settings, and calls the doInBackground() method. Moving on to mFuture:

The task wrapper class adds a callback after the task is finished, calling a handler that returns the result, and so on:

Well, it’s actually calling the postResult() method, which uses Handler to send a Message labeled MESSAGE_POST_RESULT. Get mainLooper and update UI?

(3) Handler

Following this, we define a static inner class InternalHandler:

Two types of messages are handled:

  • MESSAGE_POST_RESULT → Task end;
  • MESSAGE_POST_PROGRESS → Task progress update;

OnProgressUpdate () is called back to finish() :

Check whether the cancelled task is true. If yes, onCancelled() is called. Otherwise, onPostExecute() is called and the task status is set to FINISHED.

At this point, the AsyncTask source code has been roughly completed, and the main points are briefly summarized:

In parallel:

  • Thread pool (maximum size 128) to execute tasks;
  • Task flow status (todo, running, finished);
  • The cancellation of the task is realized by modifying a flag bit. The same processing method will be called regardless of the success or failure of the task execution.
  • Update UI-related callbacks via the Handler message mechanism;

serial

  • Add one more thread pool, synchronization lock control task in and out of the queue, the task is thrown to another thread pool processing, indirect implementation of the serial execution of the task ~

reference

  • AsyncTask(AsyncTask)

  • In-depth look at the aging AsyncTask based on Android10.0 code

  • Android AsyncTask Deprecated, Now What?