AsyncTask
长久以来,AsyncTask在Android开发中一直扮演着一个重要的角色,它主要用于执行一些不太长的异步任务。作为用来替代Thread + Handler的辅助类,AsyncTask可以很轻松地执行异步任务并更新ui,但由于context泄露,回调遗漏,configuration变化导致崩溃,平台差异性等原因,在api 30(Android 11)中AsyncTask被正式废弃:
deprecated!
被弃用后,Android给出了两个替代的建议:
-
java.util.concurrent
包下的相关类,如Executor,ThreadPoolExecutor,FutureTask。 - kotlin并发工具,那就是协程 - Coroutines了。
Coroutines
随着kotlin在Android开发中的逐渐主流化,协程的地位也在不断提高,在Android开发者官网的kotlin页面中,能看到协程作为其特性之一被列出来:
谷歌为何推荐使用协程?
个人认为,第一个原因是kotlin,作为谷歌干儿子的kotlin已经成为Android首要开发语言,协程作为其特性之一,被钦定为AsyncTask的替代者也很正常。
而更重要的原因,kotlin的协程具有很多优点,在Android上大有可为:
- 结构化并发,用同步的方式写异步代码,可以帮助减少内存泄露等问题。
- 不需要写回调,使异步代码清晰,简洁。
- 支持取消,可以很好地与Activity/Fragment的生命周期搭配使用。
- 轻量级:协程是轻量级的线程,可以在一个线程上运行多个协程,协程支持暂停而不会造成线程阻塞。
协程的简单使用(一个有点抽象的新闻加载例子)
- Retrofit:使用
suspend
关键字修饰接口:
@GET("news?type=latest")
suspend fun getLatestNews() : List<News>
- 定义CoroutineScope:
private val coroutineScope = CoroutineScope(Dispatchers.Main)
- 异步代码:
private fun loadNews() = coroutineScope.launch {
val news = newsService.getLatestNews()
newsAdapter.updateList(news)
}
- 同时,由于支持取消,可以很轻松地在Activity销毁时取消任务:
override fun onDestroy() {
super.onDestroy()
coroutineScope.cancel()
}
如果使用了lifecycle库,可以在Activity直接使用lifecycleScope
,在ViewModel中使用viewModelScope
,这样一来。我们无需手动定义CoroutineScope和取消任务。
对于协程的异常处理,我们可以直接在协程代码中捕获:
val news = try {
newsService.getLatestNews()
} catch (e: Exception) {
null
}
也可以使用CoroutineExceptionHandler:
private val errorHandler = CoroutineExceptionHandler { coroutineContext, e ->
// Handle error
}
在定义coroutineScope
时:
private val coroutineScope = CoroutineScope(Dispatchers.Main + errorHandler)
或在调用coroutineScope.launch()
时:
fun loadNews() = coroutineScope.launch(errorHandler) {
}
在RxJava在Android上兴起之时,面对如此优雅而强大的对手,可以预想到自身不足的AsyncTask肯定会被淘汰,没想到最后把它打倒的却是kotlin的协程,kotlin果然老后浪了。
网友评论