Android面试题 - AsyncTask
一、原理
AsyncTask 本质上是对handler和线程池对封装,在线程池中执行耗时任务,当任务完成或任务更新时,向主线程的Handler发送消息,在Handler中执行finish()
、onProgressUpdate()
等方法。
二、并行还是串行执行
从 1.5 引入的时候的确是串行的,在 1.6-2.3.2 的时候执行顺序更改为并行了,在 3.0 之后又改回了串行。
2.1 并行执行
并行执行任务的方法:executeOnExecutor(AsyncTask.THREAD_POOL_EXRCUTOR);
或者使用自己的创建的线程池。
2.2 串行执行
通过SerialExecutor
来控制,由于AsyncTask
中的控制线程池sDefaultExecutor
是静态的,因此一个进程内的所有AsyncTask
共用一个线程池。
如何控制串行执行?
在SerialExecutor
中,线程是在scheduleNext()
中提交给线程池执行的。
1、当SerialExecutor
第一次执行线程时,mActive为空,因此会直接将线程交给线程池执行
2、当继续执行AsyncTask
任务时,SerialExecutor
并不会将线程提交给线程池,而是等上一个Runnable执行完成后
再执行scheduleNext()
,以达到串行执行的效果。
private static class SerialExecutor implements Executor { |
三、优缺点
3.1 缺点
1、内存泄漏
如果AsyncTask被声明为Activity的非静态内部类,那么AsyncTask会保留一个对Activity的引用。如果Activity已经被销毁,AsyncTask的后台线程还在执行,它将继续在内存里保留这个引用,导致Activity无法被回收,引起内存泄漏。
2、结果丢失
屏幕旋转或Activity在后台被系统杀掉等情况会导致Activity的重新创建,之前运行的AsyncTask会持有一个之前Activity的引用,这个引用已经无效,这时调用onPostExecute()再去更新界面将不再生效。
3、生命周期
很多开发者会认为一个在Activity中创建的AsyncTask会随着Activity的销毁而销毁。然而事实并非如此。AsynTask会一直执行,直到doInBackground()方法执行完毕,然后,如果cancel(boolean)被调用,那么onCancelled(Result result)方法会被执行;否则,执行onPostExecute(Result result)方法。如果我们的Activity销毁之前,没有取消AsyncTask,这有可能让我们的应用崩溃(crash)。因为它想要处理的view已经不存在了。所以,我们是必须确保在销毁活动之前取消任务。总之,我们使用AsyncTask需要确保AsyncTask正确的取消
4、execute()只能执行一次,因为代码中判断了状态;并且只能在UI线程中调用、因为onPreExecute,在execute中被调用,而onPreExecute被限制只能在UI线程中调用
5、AsyncTask必须在主线程中创建,因为它的onPreExecute、doInBackground等方法只能在UI线程中被调用
6、api 30 (Android11)将移除该库了
3.2 优点
可以在后台任务执行完毕时根据返回结果相应的更新 UI
参考地址
Android面试题 - AsyncTask