AsyncTask理解

AsyncTask用法

以下就是AsyncTask使用方法


AsyncTask源码解析

asyncTask.execute()执行开始 初始化一个AsyncTask调用无参构造器



实例化了一个WorkerRunnable对象 mWorker实际是一个Callable



实例化了一个FutureTask对象 mfuture实际是一个Runnable,传入参数mWorker ,这两个后面会用到


然后execute方法里面调用了executeOnExecutor()方法


execute()只能调用一次的原因也在这里面,RUNNING表示正在运行 FINISHED 已执行完毕。
onPreExecute()方法是第一个调用,在这个方法里面可以做一些初始化的操作。
exec.execute(mFuture) exec 可能会有人疑问这个是什么?
我们先来看exec :
exec 就是sDefaultExecutor实际上就是一个串行的线程池 一个进程中所有的AsyncTask都在这个线程池中顺序执行,SerialExecutor可以从这个静态内部类分析AsyncTask执行的过程:


首先会把AsyncTask参数封装成FutureTask,实际上FutureTask是一个Runnable
然后把FutureTask交给SerialExecutor的execute方法,首先将任务插入mTasks中。如果当前并没有任务执行,就会调用scheduleNext()方法取出下一个任务执行,从这个方法可以看出AsyncTask默认是串行执行的。
实际上来说SerialExecutor并没有真正的执行任务,它只是为了保证了任务串行执行
真正执行任务的是THREAD_POOL_EXECUTOR?



THREAD_POOL_EXECUTOR是个线程池开启了一定的核心线程和工作线程。
然后调用线程池的execute()方法执行具体的耗时任务。
实际上就是调用了FutureTask的run()方法中的c.call(),c就是WorkerRunnable,所以就执行到了
mWorker的call()方法
现在就执行到了mWorker的call方法,先后执行了doInBackground()、postRelust()方法

postRelust方法中通过Handler将结果发送到UI线程进行页面数据更新

1、我们可以看到如果收到的消息是MESSAGE_POST_RESULT,表明执行完了耗时任务,调用finish方法


如果任务已经取消了,回调onCancelled()方法,否则回调 onPostExecute()方法。
2、如果收的的消息是MESSAGE_POST_PROGRESS,则调用onProgressUpdate方法更新进度。

注:InternalHandler是一个静态内部类,为了能使工作线程切换到UI线程,因此必须在UI线程加载,这就要求AsyncTask必须在主线程执行。
因为默认的是串行执行,如果需要并行执行可以跳过SerialExecutor直接使用executeOnExecutor()方法执行任务

使用不当
1.)内存泄漏
如果AsyncTask被声明为Activity/Fragment的非静态的内部类,那么AsyncTask会保留一个对创建了AsyncTask的Activity的引用。如果Activity/Fragment已经被销毁,AsyncTask的后台线程还在执行,它将继续在内存里保留这个引用,导致Activity无法被回收,引起内存泄露,所以最好在Activity/Fragment的onDestory()调用 cancel(boolean)。
2.) 结果丢失
屏幕旋转或Activity在后台被系统杀掉等情况会导致Activity的重新创建,之前运行的AsyncTask(非静态的内部类)会持有一个之前Activity的引用,这个引用已经失效,这时调用onPostExecute()再去更新界面将不再生效。