别再使用AsyncTask了,它已经被正式弃用了

AsyncTask

长久以来,AsyncTask在Android开发中一直扮演着一个重要的角色,它主要用于执行一些不太长的异步任务。作为用来替代Thread + Handler的辅助类,AsyncTask可以很轻松地执行异步任务并更新ui,但由于context泄露,回调遗漏,configuration变化导致崩溃,平台差异性等原因,在api 30(Android 11)中AsyncTask被正式废弃:


deprecated!

被弃用后,Android给出了两个替代的建议:

  1. java.util.concurrent包下的相关类,如ExecutorThreadPoolExecutorFutureTask
  2. kotlin并发工具,那就是协程 - Coroutines了。

Coroutines

随着kotlin在Android开发中的逐渐主流化,协程的地位也在不断提高,在Android开发者官网的kotlin页面中,能看到协程作为其特性之一被列出来:

协程已经被官方钦定

谷歌为何推荐使用协程?
个人认为,第一个原因是kotlin,作为谷歌干儿子的kotlin已经成为Android首要开发语言,协程作为其特性之一,被钦定为AsyncTask的替代者也很正常。
而更重要的原因,kotlin的协程具有很多优点,在Android上大有可为:

  1. 结构化并发,用同步的方式写异步代码,可以帮助减少内存泄露等问题。
  2. 不需要写回调,使异步代码清晰,简洁。
  3. 支持取消,可以很好地与Activity/Fragment的生命周期搭配使用。
  4. 轻量级:协程是轻量级的线程,可以在一个线程上运行多个协程,协程支持暂停而不会造成线程阻塞。

协程的简单使用(一个有点抽象的新闻加载例子)

  1. Retrofit:使用suspend关键字修饰接口:
@GET("news?type=latest")
suspend fun getLatestNews() : List<News>
  1. 定义CoroutineScope:
private val coroutineScope = CoroutineScope(Dispatchers.Main)
  1. 异步代码
private fun loadNews() = coroutineScope.launch {
    val news = newsService.getLatestNews()
    newsAdapter.updateList(news)
}
  1. 同时,由于支持取消,可以很轻松地在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果然老后浪了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容