Android 开发精要系列文章

Asynctask的开发精要

2016-12-07  本文已影响9人  ahking17
生命周期方法

注意区分哪些方法运行在UI线程, 哪些方法运行在worker thread.

asynctask.jpg
使用Asynctask的目的

使用场景: 在worker thread中执行耗时任务,并将任务的结果用于更新UI.

如果只是需要在一个worker thread中执行耗时操作,
没有更新UI的需要, 就没必要去使用Asynctask, 直接new Thread(runnable).start()就好了.
但在项目中, 经常能看到乱用Asynctask的地方,
比如创建快捷方式的代码, ShortCutUtil.java createHaosouShortCut(), 明明构造一个intent, 通过context.sendBroadcast(intent)就可以通知桌面创建快捷方式的图标, 但非要使用一个Asynctask去执行, 这样使用Asynctask就是不当的.

调用execute()和executeOnExecutor()的区别

一个进程中的多个Asynctask对象的执行是被Asynctask类统一管理的.
调用execute(), 一个进程中的多个Asynctask对象在Android 3.0以上串行的执行任务, 在Android 3.0以下是并行的执行任务. 如果需要在Android 3.0以上并行的执行多个Asynctask对象的任务, 需要调用Android 3.0以上新加的API,executeOnExecutor().
所以, 项目统一提供了一个ParallelAsyncTask类, 给了一个parallelExecute() API, 方便项目中正确使用Asynctask类, 让一个进程中的多个Asynctask对象并行的执行.

public abstract class ParallelAsyncTask<Params, Progress, Result> extends
        AsyncTask<Params, Progress, Result> {
    public final ParallelAsyncTask<Params, Progress, Result> parallelExecute(Params... params) {
        try {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
                return (ParallelAsyncTask<Params, Progress, Result>) super.executeOnExecutor(
                        THREAD_POOL_EXECUTOR, params);
            } else {
                return (ParallelAsyncTask<Params, Progress, Result>) super.execute(params);
            }
        } catch (Throwable e) {
            e.printStackTrace();
            return this;
        }
    }
}
使用细节
1. 创建Asynctask对象, 以及调用execute()或executeOnExecutor()的操作都要在UI线程

2. 停止Asynctask, 调用cancel(boolean mayInterruptIfRunning) API, mayInterruptIfRunning参数为true.

3. 一个Asynctask对象只能执行一次, 即只能对它调用一次execute()或executeOnExecutor(), 对同一个对象再次调用执行则会报运行时异常.
底层实现

Asynctask有一个static的线程池对象, 用于执行一个进程中的所有Asynctask对象.

public static final Executor THREAD_POOL_EXECUTOR
            = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
                    TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);

还有一个Handler对象, 用于在handleMessage(Message msg)中, 在UI线程调用onProgressUpdate(Progress... values)和onPostExecute(Result result)

private static InternalHandler sHandler;
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;
        }
    }
}

-----DONE.-----

上一篇下一篇

猜你喜欢

热点阅读