Brief analysis of Android 'asynctask'

Keywords: Android less

Brief analysis of Android 'asynctask'

A brief analysis of AsyncTask

Classic asynchronous task: AsyncTask. Scenarios include batch download, batch copy, etc. The official document directly gives an example of bulk downloading.

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

    // Once created, a task is executed very simply:
    new DownloadFilesTask().execute(url1, url2, url3);

Here are a few classic questions in AsyncTask:

  1. How many threads does AsyncTask have?
  2. How does AsyncTask implement thread scheduling?

Well, I think of these two questions. The first problem, obviously, is the pit. The answer is unknown. Look at the number of CPUs on the phone.

private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
// We want at least 2 threads and at most 4 threads in the core pool,
// preferring to have 1 less than the CPU count to avoid saturating
// the CPU with background work
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;

Then there is the second question. The simple answer is a sentence, which starts the thread to execute the specific logic, and then sends the result to the main thread through the handler.

If you trace further, you will find that AsyncTask = ThreadPoolExecutor + Handler.

As can be seen from the source code, AsyncTask has completed all preparations in the construction method.

  • MainHandler has been created.
  • FutureTask is ready. (to be honest, FutureTask is so sad that it makes people spit blood.)

         public AsyncTask(@Nullable Looper callbackLooper) {
         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
                     result = doInBackground(mParams);  // Mparam core logic
                     Binder.flushPendingCommands();
                 } catch (Throwable tr) {
                     mCancelled.set(true);
                     throw tr;
                 } finally {
                     postResult(result);  // Core logic
                 }
                 return result;
             }
         };
    
         mFuture = new FutureTask<Result>(mWorker) {
             @Override
             protected void done() {
                 try {
                     postResultIfNotInvoked(get());  // 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);
                 }
             }
         };
     }
  • Department news

      @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;  // Core logic
          exec.execute(mFuture);   // Core logic
    
          return this;
      }
    
      // Core logic: handler, send the result to the main thread
      private Result postResult(Result result) {
          @SuppressWarnings("unchecked")
          Message message = getHandler().obtainMessage(MESSAGE_POST_RESULT,
                  new AsyncTaskResult<Result>(this, result));
          message.sendToTarget();
          return result;
      }
    //Original address https://www.cnblogs.com/pythoncat/p/10514933.html
    

Posted by designerguy on Sat, 30 Nov 2019 12:18:04 -0800