Android協(xié)程代替Handler使用示例詳解
引言
在 Android 開發(fā)中,我們經(jīng)常需要處理異步任務(wù),例如網(wǎng)絡(luò)請求、數(shù)據(jù)庫訪問、耗時計算等等。為了在處理異步任務(wù)時能夠方便地更新 UI,Android 提供了 Handler 類。然而,在使用 Handler 時,我們需要處理一些繁瑣的問題,例如線程間通信和內(nèi)存泄漏。為了簡化這些問題,Google 在 Android 3.0 引入了 AsyncTask 類,但它仍然有一些限制。最近,Kotlin 官方推出了 Kotlin 協(xié)程,它是一種輕量級的線程框架,可以在 Android 開發(fā)中替代 Handler 和 AsyncTask,并提供更加簡潔和強(qiáng)大的異步編程體驗。
什么是協(xié)程
協(xié)程是一種輕量級的線程框架,它允許開發(fā)者以順序的方式編寫異步代碼,而無需關(guān)心線程的管理和同步問題。協(xié)程的概念最早出現(xiàn)在 Erlang 語言中,后來被其他編程語言引入。Kotlin 協(xié)程是基于 JVM 的一種協(xié)程實現(xiàn),它允許開發(fā)者以同步的方式編寫異步代碼,并且可以與現(xiàn)有的異步框架(例如 Retrofit、Room 等)很好地集成。
使用協(xié)程的好處主要有以下幾點:
- 簡化異步代碼:協(xié)程允許我們以順序的方式編寫異步代碼,而不是嵌套的回調(diào)函數(shù)或者復(fù)雜的線程管理代碼。
- 避免回調(diào)地獄:使用協(xié)程,我們可以將異步任務(wù)的邏輯寫在一個連續(xù)的代碼塊中,而不是多個回調(diào)函數(shù)中,提高代碼的可讀性和可維護(hù)性。
- 更好的錯誤處理:協(xié)程提供了異常處理機(jī)制,可以很方便地捕獲和處理異步任務(wù)中的異常。
- 更好的性能:協(xié)程使用非阻塞的方式執(zhí)行異步任務(wù),可以更好地利用系統(tǒng)資源,提高應(yīng)用的性能。
- 更好的 UI 交互:協(xié)程允許我們在主線程中執(zhí)行異步任務(wù),從而方便地更新 UI。
使用協(xié)程代替 Handler
在 Android 中,我們經(jīng)常需要在子線程中執(zhí)行一些耗時的任務(wù),然后在主線程中更新 UI。使用 Handler,我們可以很方便地實現(xiàn)這個功能。然而,使用 Handler 時,我們需要處理一些繁瑣的問題,例如線程間通信和內(nèi)存泄漏?,F(xiàn)在,我們可以使用協(xié)程來簡化這些問題。
首先,我們需要添加協(xié)程庫的依賴。在項目的 build.gradle 文件中,加入以下代碼:
dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.1'
}接下來,我們可以在任何一個函數(shù)中創(chuàng)建一個協(xié)程。在 Kotlin 中,我們使用 suspend 修飾符來聲明一個掛起函數(shù),它可以在協(xié)程中被調(diào)用。在協(xié)程中,我們可以使用 launch 函數(shù)來啟動一個新的協(xié)程,并在其中執(zhí)行一些異步任務(wù)。
下面是官方一個使用協(xié)程替代 Handler 的示例代碼:
fun main(args: Array<String>) {
launch(CommonPool) {
delay(1000L)
println("World!")
}
println("Hello,")
Thread.sleep(2000L)
}
/*
運(yùn)行結(jié)果: ("Hello,"會立即被打印, 1000毫秒之后, "World!"會被打印)
Hello,
World!
*/此處解釋一下delay方法:
在協(xié)程里delay方法作用等同于線程里的sleep, 都是休息一段時間, 但不同的是delay不會阻塞當(dāng)前線程, 而像是設(shè)置了一個鬧鐘, 在鬧鐘未響之前, 運(yùn)行該協(xié)程的線程可以被安排做了別的事情, 當(dāng)鬧鐘響起時, 協(xié)程就會恢復(fù)運(yùn)行.
在Android中使用協(xié)程
在Android中使用協(xié)程需要引入如下兩個庫:
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.1" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.1"
官方建議有生命周期的類繼承 CoroutineSocpe,這樣就能讓全部協(xié)程跟著生命周期結(jié)束。
MainActivity : AppCompatActivity(), CoroutineScope by MainScope(){
override fun onDestroy(){
super.onDestory()
cancel()
}
}在村莊UI邏輯類中使用:
class MainActivityFacede : CoroutineScope {
private val job = Job()
override val coroutineContext: CoroutineContext
get() = Dispatchers.Main + job
fun destroy() {
job.cancel()
}
}運(yùn)行協(xié)程
Android有兩種運(yùn)行協(xié)程,分別是launch與async。下面我們來說一下它們的一些區(qū)別:
- aunch 沒有返回值,或者說返回只是 job ,能夠知道任務(wù)的狀態(tài),卻不能攜帶返回結(jié)果。
- async 有返回值,也就是返回的是 Deferred ,它是繼承的 job ,所有job有的,它都有,還具備了job沒有的攜帶數(shù)據(jù)回來的能力。
- launch 可以用來運(yùn)行不需要操作結(jié)果的協(xié)程(如文件刪除,創(chuàng)建等)
- async 可以用來運(yùn)行異步耗時任務(wù)并且需要返回值的任務(wù)(網(wǎng)絡(luò)請求,數(shù)據(jù)庫操作,文件讀寫等)。
以下是Job和Deferred的生命周期說明。

以下是一個使用示例:
private suspend fun getWebTime(): Long {
var result = RequeastTest.getInstance().start()
val name = Thread.currentThread().name
if (!coroutines.contains(name)) {
coroutines.add(name)
}
return result
}
launch() {
//do sth
var time = withContext(Dispather.IO){
getWebTime()
}
//update UI
}
launch {
var deferred = async(Dispather.IO) {
//發(fā)起網(wǎng)絡(luò)請求..
getWebTime()
}
//do sth ...
var value = deferred.await()
//do sth...
}可以看到,我們使用了兩個新的東西Dispather和suspend。
Dispther可以理解為是一個協(xié)程調(diào)度器,用來調(diào)度協(xié)程跑到哪個線程中。Dispather 可以在 launch、async 等啟動協(xié)程時,指定在哪個線程里面運(yùn)行,也可以在協(xié)程中,使用 withContext(Dispather.) 來切換線程,使用 withContext 切換線程時,有返回值。
Suspend是協(xié)程里面唯一一個修飾符,用來修改函數(shù)的,表明函數(shù)是一個掛起函數(shù),協(xié)程編譯器會在編譯期間進(jìn)行CPS變換,去做一些不可描述的事情。用suspend修飾的函數(shù),只能在協(xié)程體和同樣使用 suspend 修飾的函數(shù)中調(diào)用。
另外,我們還可以同時進(jìn)行多個網(wǎng)絡(luò)請求,并在全部請求完畢之后進(jìn)行數(shù)據(jù)整理,統(tǒng)一渲染界面,如下所示。
launch {
var userInfoDeferred = async {
//獲取用戶基本信息
getUserInfo(aid)
}
var userTeamsDeferred = async{
//獲取用戶團(tuán)隊..
getUserTeams(aid)
}
var userOrgsDeferred = async {
//獲取用戶組織機(jī)構(gòu)
getUserOrgs(aid)
}
var userInfo = userInfoDeferred.await()
var userTeams = userTeamsDeferred.await()
var userOrgsDeferred = userOrgsDeferred.await()
//渲染UI
}事實上,對于協(xié)程的簡單理解與使用,協(xié)程到底是什么, 很難給出具體的定義, 就算能給出具體定義, 也會非常抽象難以理解的。另一方面, 協(xié)程可以說是編譯器的能力, 因為協(xié)程并不需要操作系統(tǒng)和硬件的支持(線程需要), 是編譯器為了讓開發(fā)者寫代碼更簡單方便, 提供了一些關(guān)鍵字, 并在內(nèi)部自動生成了一些支持型代碼。
總的來說,協(xié)程就是一種輕量級的線程框架,它允許開發(fā)者以順序的方式編寫異步代碼。并且,相比傳統(tǒng)的 Handler 和 AsyncTask編程,協(xié)程能夠更好的利用系統(tǒng)資源,提高代碼的可讀性和可維護(hù)性。
以上就是Android 協(xié)程代替Handler使用示例詳解的詳細(xì)內(nèi)容,更多關(guān)于Android 協(xié)程代替Handler的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android多功能視頻播放器GSYVideoPlayer開發(fā)流程
怎么在Android中實現(xiàn)GSYVideoPlayer視頻播放器?很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲2022-11-11
Android貝塞爾曲線初步學(xué)習(xí)第二課 仿QQ未讀消息氣泡拖拽黏連效果
這篇文章主要為大家詳細(xì)介紹了Android貝塞爾曲線初步學(xué)習(xí)的第二課,仿QQ未讀消息氣泡拖拽黏連效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-03-03
Android中AlarmManager+Notification實現(xiàn)定時通知提醒功能
本篇文章主要介紹了Android中AlarmManager+Notification實現(xiàn)定時通知提醒功能,非常具有實用價值,需要的朋友可以參考下2017-10-10
Android編程實現(xiàn)兩個Activity之間共享數(shù)據(jù)及互相訪問的方法
這篇文章主要介紹了Android編程實現(xiàn)兩個Activity之間共享數(shù)據(jù)及互相訪問的方法,簡單分析了Android中Activity數(shù)據(jù)共享與訪問的相關(guān)技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-11-11
Flutter定義tabbar底部導(dǎo)航路由跳轉(zhuǎn)的方法
這篇文章主要為大家詳細(xì)介紹了Flutter定義tabbar底部導(dǎo)航路由跳轉(zhuǎn)的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-07-07
Android進(jìn)階CoordinatorLayout協(xié)調(diào)者布局實現(xiàn)吸頂效果
這篇文章主要為大家介紹了Android進(jìn)階CoordinatorLayout協(xié)調(diào)者布局實現(xiàn)吸頂效果,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01
android初學(xué)者必須掌握的Activity狀態(tài)的四大知識點(必讀)
本篇文章主要介紹了android activity的四種狀態(tài),詳細(xì)的介紹了四種狀態(tài),包括Running狀態(tài)、Paused狀態(tài)、Stopped狀態(tài)、Killed狀態(tài),有興趣的可以了解一下。2016-11-11

