Basic usage and source code analysis of AsyncTask in Android (API 23)

Source: Internet
Author: User

Basic usage and source code analysis of AsyncTask in Android (API 23)

The Android UI is thread-insecure. to update the UI in a child thread, you must use the Android Asynchronous Operation Mechanism. Updating the UI directly in the main thread will cause the program to crash.
Android has two types of asynchronous operations: AsyncTask and Handler. AsyncTask is a lightweight asynchronous class that is simple and controllable. This article mainly explains what AsyncTask is based on the source code of API 23.

Basic usage

Declaration: The implementation methods of the same class in different API versions of Android may be different. This article explains based on the source code of the latest API 23.

public abstract class AsyncTask
  

Params: parameters passed in during execution
Progress: Progress of background tasks
Result: Return Value

AsyncTask is an abstract class, so you need to define a class to inherit it. For example:

class MyAsyncTask extends AsyncTask
   
Execute (Params... Params) to execute asynchronous tasks. OnPreExecute (), in execute (Params... Params) is executed after the call. Initialization operations on the interface, such as displaying a progress bar dialog box. DoInBackground (Params... Params), which is executed after onPreExecute () is completed. It is used to perform time-consuming operations. If the third generic parameter of AsyncTask specifies Void, the task execution result is not returned. You can call publishProgress (Progress... To update the progress. Note: UI operations cannot be performed in this method.. OnProgressUpdate (Progress... Values), call publishProgress (Progress... This method is executed to update the progress information to the UI component. OnPostExecute (Result result): When the background operation ends, this method will be called, and the calculation Result will be passed as a parameter to this method. You can use the returned data to perform some UI operations, for example, to remind the task execution result, and to close the progress bar dialog box. Example

Create an Activity, a Button, and a ProgressBar. click the Button to start an AsyncTask and update the ProgressBar status in real time.

MyAsyncTask
Class MyAsyncTask extends AsyncTask
    
     
{@ Override protected void onPreExecute () {super. onPreExecute () ;}@ Override protected void onPostExecute (Boolean deny lean) {super. onPostExecute (lean) ;}@ Override protected void onProgressUpdate (Integer... values) {super. onProgressUpdate (values); progressBar. setProgress (values [0]);} @ Override protected Boolean doInBackground (Void... params) {for (int I = 0; I <100; I ++) {// call publishProgress to trigger onProgressUpdate method publishProgress (I); try {Thread. sleep (300);} catch (InterruptedException e) {e. printStackTrace () ;}} return true ;}@ Override protected void onCancelled () {super. onCancelled (); progressBar. setProgress (0 );}}
    
Click method of Button
startAsyncBtn.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                myAsyncTask = new MyAsyncTask();                myAsyncTask.execute();            }        });
Source code analysis

Through the above example, we can find that AsyncTask is easy to use. It is very convenient to create a new sub-thread in the main thread for UI update and other operations. However, its implementation is not as easy as it is to use. The following is an analysis of the source code of AsyncTask.

Constructor of AsyncTask
public AsyncTask() {        mWorker = new WorkerRunnable
     
      () {            public Result call() throws Exception {                mTaskInvoked.set(true);                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);                //noinspection unchecked                Result result = doInBackground(mParams);                Binder.flushPendingCommands();                return postResult(result);            }        };        mFuture = new FutureTask
      
       (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);                }            }        };    }
      
     

In the constructor, only two things are done: Initialize the mWorker and mFuture variables. MWorker is a Callable object and mFutre is a FutureTask object. Execute () is used.

Execute (Params... Params)
 public final AsyncTask
       
         execute(Params... params) {        return executeOnExecutor(sDefaultExecutor, params);    }
       

Only one line of code calls the executeOnExecutor method. sDefaultExecutor is actually a serial thread pool, and all AsyncTask in a process is queued for execution in this serial thread pool. The executeOnExecutor source code is as follows.

public final AsyncTask
        
          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;        exec.execute(mFuture);        return this;    }
        

It can be seen that onpreexecute(execute(is used in this example to execute the execution process of the thread pool under exec.exe cute (mFuture.

private static class SerialExecutor implements Executor {        final ArrayDeque
         
           mTasks = new ArrayDeque
          
           ();        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 system first encapsulates the Params parameter of AsyncTask as the FutureTask object. FutureTask is a concurrent class, which is equivalent to Runnable. Then, it submits the FutureTask to the execute method of SerialExecutor, it first inserts the FutureTask into the task queue tasks. If there is no active AsyncTask task at this time, it will execute the next AsyncTask task. After an AsyncTask task is executed, asyncTask continues executing other tasks until all tasks are executed.It can be seen from this that, by default, AsyncTask is executed in serial mode.
Let's take a look at the AsyncTask constructor. When mFuture is constructed, mWork is passed as a parameter. The mFuture run method calls the call () method of mWork, so call () it will be executed in the thread pool. Call () calls doInBackground () and gives the returned result to postResult.

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

You can see that a Handler is obtained through getHandler () in postResult.

  private static Handler getHandler() {        synchronized (AsyncTask.class) {            if (sHandler == null) {                sHandler = new InternalHandler();            }            return sHandler;        }    }

View the getHandler source code. You can find that getHandler returns an InternalHandler. Let's take a look at the source code of InternalHandler.

private static class InternalHandler extends Handler {        public InternalHandler() {            super(Looper.getMainLooper());        }        @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;            }        }    }

It is clear that InternalHandler is a class that inherits Handler and judges msg in its handleMessage () method. If it is MESSAGE_POST_RESULT, finish () is executed. If it is MESSAGE_POST_PROGRESS, and then execute onProgressUpdate ().
MESSAGE_POST_PROGRESS message is sent in publishProgress. For details, see the source code.

protected final void publishProgress(Progress... values) {        if (!isCancelled()) {            getHandler().obtainMessage(MESSAGE_POST_PROGRESS,                    new AsyncTaskResult
(this, values)).sendToTarget(); } }Finish ()
private void finish(Result result) {        if (isCancelled()) {            onCancelled(result);        } else {            onPostExecute(result);        }        mStatus = Status.FINISHED;    }

If the current task is canceled, the onCancelled () method is called. If onPostExecute () is not called ().

Note: The AsyncTask class must be loaded in the main thread. This process has been automatically completed by the system in Android 4.1 and later versions. The AsyncTask object must be created in the main thread, and the execute method must be called in the UI thread. An AsyncTask object can only be executed once, that is, the execute method can only be called once. Otherwise, an exception occurs during running. Differences between different versions

Before Android 1.6, AsyncTask is used to execute tasks in a serial manner. In Android 1.6, AsyncTask adopts the thread pool to process tasks in parallel. However, starting from Android 3.0, to avoid concurrent errors caused by AsyncTask, asyncTask uses another thread for serial task execution. However, in Android 3.0 and later versions, we can use the executeOnExecutor method of AsyncTask to execute tasks in parallel. However, this method is newly added to Android 3.0 and cannot be used in earlier versions.

Summary

The source code of the entire AsyncTask has been analyzed. After analyzing the source code, we can find that AsyncTask is not mysterious,His essence is Handler..
Now we know how to use AsyncTask, when the methods will be called, what is the role, and what is the relationship between them, I believe that you will not be afraid of any problems arising from AsyncTask in the future, because the entire source code of AsyncTask has been turned upside down. What are you afraid.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.