Android: AsyncTask use and analysis

Foreword

AsyncTask, HandlerThrad, IntentServiceAre on the Android messaging packages and applications, solve the problem child thread time-consuming task, the main thread to update the UI.

AsyncTask use

AsyncTask is an abstract class, subclass inherits by rewriting doInBackground, which runs a sub-thread.

public class DownloadTask extends AsyncTask<String,Integer,String> {

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
    }

    @Override
    protected String doInBackground(String... strings) {
        publishProgress(1);
        return "AsyncTask";
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
    }
}
复制代码

AsyncTask<Params, Progress, Result>Generic parameters, according to business needs, pass different types. The first parameter Paramsrefers to passed doInBackgroundURL parameter type, such as blind ah schedule. The second parameter Progressrefers to the execution doInBackgroundtime of the method, the publishProgressprogress of the state of progress of update type, such as downloaded. The third parameter Resultis doInBackgroundthe end of the process performs spread onPostExecuteparameter types, such as downloading results.

Related Methods

  • onPreExecute()

The main thread. Before you can begin the task of UI data or preliminary preparation. Non-essential method.

  • doInBackground

(Thread pool) to run the child thread. Generally time-consuming operation, such download. AsyncTask abstract method, and must be implemented.

  • onProgressUpdate

The main thread, call publishProgress callback method will be the method doInBackground method, it displays the current task status. Used to update the download progress. Non-essential method.

  • onPostExecute

The main thread. After return value doInBackground method, the callback method. Non-essential method.

  • onCancelled

When the main thread running, the task completion callback method, indicating the end of the task.

Start Task

execute the task can only be called once, otherwise an error.

    DownloadTask task=new DownloadTask();
    task.execute("Git");
复制代码

Source code analysis

AsyncTask constructor

Android is in code comments must be called on the UI thread, the UI thread because the default has Looper, and AsyncTask needs to be updated UI. If you do not update the UI, can be created in the child thread has Looper.

    //构造方法1
    public AsyncTask() {
        this((Looper) null);
    }
    //构造方法2
    public AsyncTask(@Nullable Handler handler) {
        this(handler != null ? handler.getLooper() : null);
    }
    //构造方法3
    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);
                    Binder.flushPendingCommands();
                } catch (Throwable tr) {
                    mCancelled.set(true);
                    throw tr;
                } finally {
                    postResult(result);
                }
                return result;
            }
        };
       
        mFuture = new FutureTask<Result>(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);
                }
            }
        };
    }

复制代码

Constructor 1,2, 3 finally call the constructor. Look constructor 3 did what?

Analysis of a

MHanlder assignment to initialize. Looper first determine whether the incoming objects, if not passed, or passed Looper Looper and objects and the UI thread of the same, by calling the getMainHandlercalling method Handler object UI thread (here can be simply understood, AsyncTask created in the UI thread). If not equal, newa Handlertarget.

    //AsyncTask
    private static Handler getMainHandler() {
        synchronized (AsyncTask.class) {
            if (sHandler == null) {
                sHandler = new InternalHandler(Looper.getMainLooper());
            }
            return sHandler;
        }
    }
    //Looper
    public static Looper getMainLooper() {
        synchronized (Looper.class) {
            return sMainLooper;
        }
    }

复制代码

AsyncTask the getMainHandlermethod, by calling the Looper getMainLooperto get Looper objects (UI thread Looper Object) method and create InternalHandler. Here you can see that in the absence of incoming Looper, and does not create AsyncTask the UI thread, Looper will get less than the object. sHandler variable is InternalHandler types, inheritance Handler.

    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 the method of treatment, you can see is MESSAGE_POST_RESULTthe message and MESSAGE_POST_PROGRESSprocess messages, used at the end of the mission and progress updates, switch to the main thread, the callback related methods.

Analysis II

Static abstract class WorkerRunnable inherit Callable, more than just add an array mParams, for saving parameters. In WorkerRunnable's callapproach, calling our major rewrite doInBackground. The final call to postResultthe method.

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

In a analysis, the final processing of the objects seen InternalHandler MESSAGE_POST_RESULT message, call AsyncTask object's finishmethods.

     private void finish(Result result) {
        if (isCancelled()) {
            onCancelled(result);
        } else {
            onPostExecute(result);
        }
        mStatus = Status.FINISHED;
    }
复制代码

According to the current state of the call AsyncTask onCancelledor onPostExecutemethod.

In the configuration of AsyncTask method. By constructing Handler object, and construction WorkRunnable objects and objects used to create WorkRunnable FutureTask objects. FutureTask realized RunnableFuture interface, and RunnableFuture interface extends Runnable interface and Future interfaces. Therefore, not only do FutureTask is a Runnable Thread object directly executed, but also as a calculation result obtained for Future object of Callable.

AsyncTask execution


        DownloadTask task=new DownloadTask();

        task.execute("Git");
复制代码

We create DownloadTask objects in the UI thread, and calling DownloadTask object's executemethod, Gitthe method that we want to spread doInBackgroundthe value of the method;

    public final AsyncTask<Params, Progress, Result> execute(Params... params) {
        return executeOnExecutor(sDefaultExecutor, params);
    }
复制代码

AsyncTask call the execute方method calls executeOnExecutormethods.

   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;
        exec.execute(mFuture);

        return this;
    }
复制代码

If the current AsyncTask running object or end, will throw an exception, a task can only be run once. Here called onPreExecutemethod and parameters assigned to the variable WorkerRunable omParams object mentioned earlier. Executed by a thread pool object exex FutureTask object constructor to create the final call to WorkerRunable object callmethods to execute our overridden doInBackgroundmethod.

Here we take a look at the thread pool object sDefaultExecutor.

public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
复制代码

The class constructor 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(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);
            }
        }
    }

复制代码

By ArrayDequ save the task, and locking mechanism to execute synchronization method, serial tasks.

THREAD_POOL_EXECUTOWhat stuff?

  public static final Executor THREAD_POOL_EXECUTOR;

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

复制代码

Unsurprisingly is a thread pool.

to sum up

By tracking AsyncTask constructor, we understand the whole process of implementation AsyncTask. Looper Handler object created by an object, for transmitting a message in the thread pool, switching to the UI thread, related operations. And create WorkRunnable object calls a background task (we rewrite the doInBackgroundmethod), the WorkRunnable FutureTask object to the object so that when the thread pool, the results and process control.

In AsyncTask the executeway to track, we know the background task queue holds two-way, lock the thread pool by a synchronous serial operation.

Also note that, AsyncTask Activity life cycle and life cycle are not the same, if AsyncTask holds Activity, likely to cause a memory leak. Similarly Download consuming operation is recommended IntentServcie.

Sharing knowledge

If you feel that a useful article, the article points to a praise, iron son
If the article is incorrect or one-sided knowledge, please be corrected, thank you

Guess you like

Origin blog.csdn.net/weixin_33753845/article/details/91372146