AsyncTask问题总结

什么是AsyncTask:

android提供的轻量级的异步类。
本质上是封装了线程池和handler的异步框架。由于内部继承了handler,方便在工作线程和ui线程之间灵活地切换。

只适合做一些耗时比较短的操作,如果需要耗时比较长的操作还是要用线程池。

AsyncTask使用方法:

android提供的使用示例:

//Here is an example of subclassing:
   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);
   

三个参数

public abstract class AsyncTask<Params, Progress, Result> {
...
}

AsyncTask的三个泛型参数
Params: doInBackground 方法的参数,后台执行耗时任务
Progress: onProgressUpdate方法的参数,用于界面更新UI
Result: onPostExecute方法的参数,是返回值类型

五个方法

image

onPreExecute方法: UI线程中执行,是耗时操作执行前执行的方法,可以用来预处理数据
doInBackground方法: 耗时操作方法,耗时操作再次方法里执行,在其中可以执行一个publishProgress方法
publishProgress方法: 和onProgressUpdate方法同时使用
onProgressUpdate方法: publishProgress方法调用完毕后才会调用,可以用于异步操作执行过程中更新UI
onPostExecute方法: 异步操作执行结束后调用的方法可以用来更新UI

AsyncTask内部原理:

image

AsyncTask的工作流程:
首先是构造函数里面创建Handler和封装的 WorkRunnable 和 FeatureTask;
WorkRunnable 本质是一个 Callable 接口,FeatureTask 本质是一个 Runable。
WorkRunnable 又被封装到了 FeatureTask 里面。

所以从入口execute方法开始执行时,先执行onPreExecute方法,最终通过线程池接口执行封装的runnable,其实就是FeatureTask的run方法,FeatureTask封装了WorkRunnable,其实就是run方法里面又调用了WorkRunnable的call方法,call方法里面执行了 doInBackground 方法,call方法执行到最后会通过handler发送消息,消息有两类,一类是执行onProgressUpdate方法,一类是执行postExecute方法,两者都是发给AsyncTask来执行,因为AsyncTask是运行在主线程,call方法是运行在线程池的子线程里。

构造函数:

    public AsyncTask() {
        this((Looper) null);
    }

    /**
     * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
     *
     * @hide
     */
    public AsyncTask(@Nullable Handler handler) {
        this(handler != null ? handler.getLooper() : null);
    }

    /**
     * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
     *
     * @hide
     */
    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);
                }
            }
        };
    }

三个执行方法:

    @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) {
        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;
    }

    @MainThread
    public static void execute(Runnable runnable) {
        sDefaultExecutor.execute(runnable);
    }

这里执行的是 mFuture,mFuture里面又封装了 mWorker

THREAD_POOL_EXECUTOR实现过程

    private static final int CORE_POOL_SIZE = 1;//核心线程1个
    private static final int MAXIMUM_POOL_SIZE = 20;//最大线程20个
    private static final int KEEP_ALIVE_SECONDS = 3;//线程存活时间3秒

    public static final Executor THREAD_POOL_EXECUTOR;

    static {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
                new SynchronousQueue<Runnable>(), sThreadFactory);
        threadPoolExecutor.setRejectedExecutionHandler(sRunOnSerialPolicy);
        THREAD_POOL_EXECUTOR = threadPoolExecutor;
    }

executeOnExecutor方法中的exec参数实现过程:

    @UnsupportedAppUsage
    private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;

    public static final Executor SERIAL_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(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);
            }
        }
    }

把需要执行的Runnable放到队列里面,如果没有需要执行的mActive,就从队列里面弹出一个让线程池执行。
这里会执行Runnable的run方法。这个Runable实际上就是mFuture,mFuture是FutureTask本质上就是一个Runnable

public class FutureTask<V> implements RunnableFuture<V> {
...
}
public interface RunnableFuture<V> extends Runnable, Future<V> {
    /**
     * Sets this Future to the result of its computation
     * unless it has been cancelled.
     */
    void run();
}

mFuture是FutureTask执行run方法时会执行Callable的call方法。其实就是 mWorker 的call方法,这个call方法在AsyncTask的构造方法里实现;

    public void run() {
        if (state != NEW ||
            !U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
            return;
        try {
            Callable<V> c = callable;
            if (c != null && state == NEW) {
                V result;
                boolean ran;
                try {
                    result = c.call();
                    ran = true;
                } catch (Throwable ex) {
                    result = null;
                    ran = false;
                    setException(ex);
                }
                if (ran)
                    set(result);
            }
        } finally {
            // runner must be non-null until state is settled to
            // prevent concurrent calls to run()
            runner = null;
            // state must be re-read after nulling runner to prevent
            // leaked interrupts
            int s = state;
            if (s >= INTERRUPTING)
                handlePossibleCancellationInterrupt(s);
        }
    }

mWorker的call方法执行是调用doInBackground方法,同时最终会执行 postResult方法
这个方法其实就是通过Handler发送消息

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

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

handler这里有两种消息,一种是走finish,一种是onProgressUpdate
这里的result.mTask都是AsyncTask他自己,可以看下AsyncTaskResult封装过程。
因为

    private static class AsyncTaskResult<Data> {
        final AsyncTask mTask;
        final Data[] mData;

        AsyncTaskResult(AsyncTask task, Data... data) {
            mTask = task;
            mData = data;
        }
    }

AsyncTask的finish方法
就走到onPostExecute,整个流程就结束了。

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

AsyncTask的注意事项:

内存泄漏:

跟Handler其实一样,非静态内部类持有外部类的引用,导致如果执行耗时操作时外部类被销毁无法回收。
解决方法:
一是、通过弱引用来引用外部类。
二是、外部类Activity的onDestroy方法中执行AsyncTask的cancel方法操作

生命周期:

必须在Activity的onDestroy方法里执行AsyncTask的cancel方法来销毁AsyncTask。否则可能造成崩溃。

    private final AtomicBoolean mCancelled = new AtomicBoolean();

    public final boolean cancel(boolean mayInterruptIfRunning) {
        mCancelled.set(true);
        return mFuture.cancel(mayInterruptIfRunning);
    }

结果丢失:

比如屏幕旋转或者被后台杀掉等,Activity意外销毁,导致Activity重新创建。而之前的AsyncTask会持有之前Activity的引用,但是这个引用已经无效了。这是调用AsyncTask.onPostExectue方法更新UI时,会发现无法更新。

并行or串行:

android sdk 1.6之前串行
1.6到2.3才用并行,2.3之后又改成串行,
但是可以调用 executeOnExecutor 来执行并行操作。
但是推荐串行。可以保持线程池的稳定性。

posted @ 2022-07-07 17:39  cfdroid  阅读(28)  评论(0编辑  收藏  举报