Android AsyncTask的缺点
AsyncTask模板方法
onPreExecute()
:初始化操作doInBackground(Params...)
:后台子线程任务onProgressUpdate(Progress...)
:UI更新操作onPostExecute(Result)
AsyncTask问题
生命周期
如果创建AsyncTask的Activity销毁,AsyncTask仍会一直执行,直到doInBackground()
方法执行完毕。如果 cancel(boolean)被调用,那么onCancelled(Result result)
方法会被执行;否则,执行onPostExecute(Result result)
方法。如果我们的Activity销毁之前,没有取消 AsyncTask,这有可能让我们的AsyncTask崩溃(crash)。因为它想要处理的view已经不存在。所以,我们必须确保在销毁活动之前取消AsyncTask。
AsyncTask的cancel方法需要一个布尔值的参数,参数名为
mayInterruptIfRunning
,意思是如果正在执行是否可以打断,如果这个值设置为true,表示这个任务可以被打断,否则,正在执行的程序会继续执行直到完成。如果在doInBackground()
方法中有一个循环操作,我们应该在循环中使用isCancelled()
来判断,如果返回为true,我们应该避免执行后续无用的循环操作。如果调用AsyncTask的
cancel(false)
,doInBackground()
仍然会执行到方法结束,只是不会去调用onPostExecute()
方法。但是实际上这是让应用程序执行了没有意义的操作。那么是不是我们调用cancel(true)
前面的问题就能解决呢?并非如此。如果mayInterruptIfRunning
设置为true,会使任务尽早结束,但是如果的doInBackground()有不可中断的操作会失效,比如这个
BitmapFactory.decodeStream()` IO操作,这个操作会继续下去。但是你可以提前关闭IO流并捕获这样操作抛出的异常,但是这样会使得cancel()方法没有任何意义。
总之,我们使用AsyncTask需要确保AsyncTask正确地取消。
内存泄漏
如果AsyncTask被声明为Activity的非静态的内部类,那么AsyncTask会保留一个对创建了AsyncTask的Activity的引用。如果Activity已经被销毁,AsyncTask的后台线程还在执行,它将继续在内存里保留这个引用,导致Activity无法被回收,引起内存泄露。
结果丢失
屏幕旋转或Activity在后台被系统杀掉等情况会导致Activity的重新创建,之前运行的AsyncTask会持有一个之前Activity的引用,这个引用已经无效,这时调用onPostExecute()
再去更新界面将不再生效。
并行还是串行
在Android 1.6之前的版本,AsyncTask是串行的,在1.6至2.3的版本,改成了并行的。在2.3之后的版本又做了修改,可以支持并行和串行,当想要串行执行时,直接执行execute()
方法,如果需要并行执行,则要执行executeOnExecutor(Executor)
。
版权声明:
作者:Joe.Ye
链接:https://www.appblog.cn/index.php/2023/02/18/android-asynctask-shortcoming/
来源:APP全栈技术分享
文章版权归作者所有,未经允许请勿转载。
共有 0 条评论