3个范型参数:
Params
:启动任务执行的输入参数
Progress
:后台任务执行的百分比
Result
,后台计算的结果类型
在一个异步任务里,不是所有的类型总被用。假如一个类型不被使用,可以简单地使用Void类型:
private class MyTask extends AsyncTask<Void,Void,Void>{... }
onPreExecute
:
运行在
UI
线程。
初始化task,比如显示一个进度条。
doInBackground
,:
运行在后台线程。
主要用来进行逻辑处理。时间可以较长,可以避免在UI线程ANR。耗时操作在这个方法中进行。
在onPreExecute
之
后立刻运行。Execute的参数传入到这个接口。
正常情况,计算结果将被返回给onPostExecute
。如果 cancel(boolean)
调用,则返回结果给
onCancelled(Object)
在这个步骤也可以publishProgress(Progress...)发布进度结果到UI线程,由onProgressUpdate(Progress...)
来处理。
onProgressUpdate
:
运行在
UI
线程。
调用publishProgress(Progress...)之后运行。这部分主要用来与用户交互,比如显示进度百分比给用户。
onPostExecute
.
运行在
UI
线程。
doInBackground
运行完以后将结果返回给这个接口。
线程规则
1 AsyncTask类必须在UI线程加载。
2 任务实例必须创建在 UI线程 。
3 execute(Params...)必须在 UI线程上调用
4不要手动调用onPreExecute(),onPostExecute(Result),doInBackground(Params...),onProgressUpdate(Progress...)
5这个任务只执行一次(如果执行第二次将会抛出异常)
使用限制:
1. 多任务并发时可能存在问题。
由于AsyncTask被设计成最大10个工作队列(static),如果同时需要下载超过10个小图片,就可能导致工作队列溢出(创建超过10个实例)。
2. AsyncTask将导致Activity无法重建自己,即使设置onRetainNonConfigurationState参数。如果是自己创建的线程,则可以。不过,如果自己创建线程,一旦Activity finish时就需要及时释放。
3. 无法改变后台线程的优先级,因为设计是已经写死。
4 . 线程池设计:5个核心线程和最大能支持128个线程,一旦超过5个线程存在,并空闲超过一定时间,空闲线程将被杀死。
5. AsyncTask设计对于短时间(几秒)的后台操作表现优秀,但是如果是长时间的操作,则推荐使用java.util.concurrent
的API, 如
Executor
, ThreadPoolExecutor
and FutureTask
.
长时间的背景操作一般使用Service+Thread来实现,加上线程池,实现多线程的操作。