AsyncTask
長久以來,AsyncTask在Android開發(fā)中一直扮演著一個重要的角色届案,它主要用于執(zhí)行一些不太長的異步任務。作為用來替代Thread + Handler的輔助類罢艾,AsyncTask可以很輕松地執(zhí)行異步任務并更新ui楣颠,但由于context泄露尽纽,回調遺漏,configuration變化導致崩潰童漩,平臺差異性等原因弄贿,在api 30(Android 11)中AsyncTask被正式廢棄:
deprecated!
被棄用后,Android給出了兩個替代的建議:
-
java.util.concurrent
包下的相關類矫膨,如Executor差凹,ThreadPoolExecutor,FutureTask侧馅。 - kotlin并發(fā)工具危尿,那就是協(xié)程 - Coroutines了。
Coroutines
隨著kotlin在Android開發(fā)中的逐漸主流化馁痴,協(xié)程的地位也在不斷提高谊娇,在Android開發(fā)者官網的kotlin頁面中,能看到協(xié)程作為其特性之一被列出來:
協(xié)程已經被官方欽定
谷歌為何推薦使用協(xié)程罗晕?
個人認為济欢,第一個原因是kotlin,作為谷歌干兒子的kotlin已經成為Android首要開發(fā)語言小渊,協(xié)程作為其特性之一法褥,被欽定為AsyncTask的替代者也很正常。
而更重要的原因酬屉,kotlin的協(xié)程具有很多優(yōu)點挖胃,在Android上大有可為:
- 結構化并發(fā),用同步的方式寫異步代碼梆惯,可以幫助減少內存泄露等問題酱鸭。
- 不需要寫回調,使異步代碼清晰垛吗,簡潔凹髓。
- 支持取消,可以很好地與Activity/Fragment的生命周期搭配使用怯屉。
- 輕量級:協(xié)程是輕量級的線程蔚舀,可以在一個線程上運行多個協(xié)程,協(xié)程支持暫停而不會造成線程阻塞锨络。
協(xié)程的簡單使用(一個有點抽象的新聞加載例子)
- 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和取消任務缅叠。
對于協(xié)程的異常處理悄泥,我們可以直接在協(xié)程代碼中捕獲:
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上興起之時,面對如此優(yōu)雅而強大的對手肤粱,可以預想到自身不足的AsyncTask肯定會被淘汰弹囚,沒想到最后把它打倒的卻是kotlin的協(xié)程,kotlin果然老后浪了领曼。