Use AsyncTask

Using AsyncTask is one way to implement asynchronous tasks in Android. All AsyncTasks are executed serially

/** * Params: input parameters to start task execution * Progress: background task execution Progress * Result: Public abstract class AsyncTask<Params, Progress, Result>Copy the code
/** * Step 1: Subclass AsyncTask * note: * a. Inheriting AsyncTask * b. Specify types for three generic parameters; Void java.lang.Void instead of * c. Implement the core method */ Private Class MyTask extends AsyncTask<Params, Progress, Result> {.... as required // Method 1: onPreExecute () // Action: operation before thread task // Note: Override protected void on main thread as requiredonPreExecute() {... } // Method 2:doInBackground () : receives input arguments, executes time-consuming operations in the task, returns the result of the thread task execution // Note: The thread task must be overridden to customize the thread taskdoInBackground(String... params) { ... // Custom thread task // call publishProgress() to show progress, onProgressUpdate () publishProgress(count); } @override protected void onProgressUpdate(Integer... progresses) { ... } // Method 4: onPostExecute () // function: receive thread task execution result, display the execution result to UI component // Note: Override protected void onPostExecute(String result) {Override protected void onPostExecute(String result) } // Method 5: onCancelled() // Action: cancel the task // Note: Execute @override protected void on the main threadonCancelled() {... }} /** * Step 2: Create an instance object of the AsyncTask subclass * note: instances of the AsyncTask subclass must be created in UI thread */ MyTask mTask = new MyTask(); /** * Step 3: manually call execute(Params... Params) to perform asynchronous thread tasks * Note: * A. must be called in the UI thread * B. An AsyncTask instance can only be executed once. If executed twice, an exception will be thrown. * c. To execute a task, the system automatically calls a series of AsyncTask methods: onPreExecute(),doInBackground(), onProgressUpdate(), onPostExecute() The above method */ mtask.execute () cannot be called manually;Copy the code

AsyncTask source code analysis

AsyncTask execute Execution process

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

@MainThread
public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec, Params... Params) {// A task can be executed only onceif(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;
}
Copy the code

Executor implementation

Public static final Executor = new SerialExecutor(); public static final 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(newRunnable() {
      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); }}}Copy the code

Thread pool implementation

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;
}
Copy the code

FutureTask and Callable implementation

public AsyncTask() { this((Looper) null); } public AsyncTask(@Nullable Handler handler) { this(handler ! = null ? handler.getLooper() : null); } public AsyncTask(@nullable Looper callbackLooper) {// Default InternalHandler and main thread Looper mHandler = callbackLooper == null || callbackLooper == Looper.getMainLooper() ? getMainHandler() : new Handler(callbackLooper); Example = new WorkerRunnable<Params, Result>() {public Result Call () throws Exception {mTaskInvoked. Set (true);
      Result result = null;
      try {
        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
        result = doInBackground(mParams);
        Binder.flushPendingCommands();
      } catch (Throwable tr) {
        mCancelled.set(true);
        throw tr;
      } finally {
        postResult(result);
      }
      returnresult; }}; MFuture = new FutureTask<Result>(mWorker) {// Main thread callback @override protected voiddone() {try {// Called when the result has no callback, get() gets the task return value 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;
}
Copy the code

Handler implementation

Private static Class InternalHandler extends Handler {public InternalHandler(Looper Looper) { super(looper); } // The main thread calls @suppressWarnings ({"unchecked"."RawUseOfParameterizedType"}) @Override public void handleMessage(Message msg) { AsyncTaskResult<? > result = (AsyncTaskResult<? >) msg.obj; switch (msg.what) {caseResult.mtask. finish(result.mdata [0]);break;
      caseMESSAGE_POST_PROGRESS: / / update the progress bar result. MTask. OnProgressUpdate (result. MData);break;
    }
  }
}

private void finish(Result result) {
  if(isCancelled()) {// Task cancelled, main thread called onCancelled(result); }else{// The task returns the result and the main thread calls onPostExecute(result); } mStatus = Status.FINISHED; }Copy the code

Static variable initialization

Private static final int CPU_COUNT = Runtime.getruntime ().availableprocessors (); // We want at least 2 threads and at most 4 threads in the core thread pool, preferring one less than the number of cpus, to avoid the CPU working completely in the background. 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 int KEEP_ALIVE_SECONDS = 30; Private static Final ThreadFactory sThreadFactory = newThreadFactory() {
  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; Private static final int MESSAGE_POST_RESULT = 0x1; private static final int MESSAGE_POST_RESULT = 0x1; private static final int MESSAGE_POST_PROGRESS = 0x2; // Default thread pool private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR; private static InternalHandler sHandler;Copy the code

Non-static variable initialization

// FutureTask related private final WorkerRunnable<Params, Result> mWorker; private final FutureTask<Result> mFuture; private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> { Params[] mParams; } // AsyncTask Status private volatile Status mStatus = status.pending; /** * indicates the current state of the task, in the life of the task, */ Public enum Status {// Indicating that the task has not been executed PENDING, // indicating that the task has been executed RUNNING, // Indicating that the task has completed } private final AtomicBoolean mCancelled = new AtomicBoolean(); private final AtomicBoolean mTaskInvoked = new AtomicBoolean(); private final Handler mHandler;Copy the code

Statically executed method

@mainThread public static void execute(Runnable Runnable) {sdefaulTexecutor.execute (Runnable); }Copy the code