Android協(xié)程代替Handler使用示例詳解
引言
在 Android 開(kāi)發(fā)中,我們經(jīng)常需要處理異步任務(wù),例如網(wǎng)絡(luò)請(qǐng)求、數(shù)據(jù)庫(kù)訪問(wèn)、耗時(shí)計(jì)算等等。為了在處理異步任務(wù)時(shí)能夠方便地更新 UI,Android 提供了 Handler 類(lèi)。然而,在使用 Handler 時(shí),我們需要處理一些繁瑣的問(wèn)題,例如線程間通信和內(nèi)存泄漏。為了簡(jiǎn)化這些問(wèn)題,Google 在 Android 3.0 引入了 AsyncTask 類(lèi),但它仍然有一些限制。最近,Kotlin 官方推出了 Kotlin 協(xié)程,它是一種輕量級(jí)的線程框架,可以在 Android 開(kāi)發(fā)中替代 Handler 和 AsyncTask,并提供更加簡(jiǎn)潔和強(qiáng)大的異步編程體驗(yàn)。
什么是協(xié)程
協(xié)程是一種輕量級(jí)的線程框架,它允許開(kāi)發(fā)者以順序的方式編寫(xiě)異步代碼,而無(wú)需關(guān)心線程的管理和同步問(wèn)題。協(xié)程的概念最早出現(xiàn)在 Erlang 語(yǔ)言中,后來(lái)被其他編程語(yǔ)言引入。Kotlin 協(xié)程是基于 JVM 的一種協(xié)程實(shí)現(xiàn),它允許開(kāi)發(fā)者以同步的方式編寫(xiě)異步代碼,并且可以與現(xiàn)有的異步框架(例如 Retrofit、Room 等)很好地集成。
使用協(xié)程的好處主要有以下幾點(diǎn):
- 簡(jiǎn)化異步代碼:協(xié)程允許我們以順序的方式編寫(xiě)異步代碼,而不是嵌套的回調(diào)函數(shù)或者復(fù)雜的線程管理代碼。
- 避免回調(diào)地獄:使用協(xié)程,我們可以將異步任務(wù)的邏輯寫(xiě)在一個(gè)連續(xù)的代碼塊中,而不是多個(gè)回調(diào)函數(shù)中,提高代碼的可讀性和可維護(hù)性。
- 更好的錯(cuò)誤處理:協(xié)程提供了異常處理機(jī)制,可以很方便地捕獲和處理異步任務(wù)中的異常。
- 更好的性能:協(xié)程使用非阻塞的方式執(zhí)行異步任務(wù),可以更好地利用系統(tǒng)資源,提高應(yīng)用的性能。
- 更好的 UI 交互:協(xié)程允許我們?cè)谥骶€程中執(zhí)行異步任務(wù),從而方便地更新 UI。
使用協(xié)程代替 Handler
在 Android 中,我們經(jīng)常需要在子線程中執(zhí)行一些耗時(shí)的任務(wù),然后在主線程中更新 UI。使用 Handler,我們可以很方便地實(shí)現(xiàn)這個(gè)功能。然而,使用 Handler 時(shí),我們需要處理一些繁瑣的問(wèn)題,例如線程間通信和內(nèi)存泄漏?,F(xiàn)在,我們可以使用協(xié)程來(lái)簡(jiǎn)化這些問(wèn)題。
首先,我們需要添加協(xié)程庫(kù)的依賴。在項(xiàng)目的 build.gradle 文件中,加入以下代碼:
dependencies { implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.1' }
接下來(lái),我們可以在任何一個(gè)函數(shù)中創(chuàng)建一個(gè)協(xié)程。在 Kotlin 中,我們使用 suspend 修飾符來(lái)聲明一個(gè)掛起函數(shù),它可以在協(xié)程中被調(diào)用。在協(xié)程中,我們可以使用 launch 函數(shù)來(lái)啟動(dòng)一個(gè)新的協(xié)程,并在其中執(zhí)行一些異步任務(wù)。
下面是官方一個(gè)使用協(xié)程替代 Handler 的示例代碼:
fun main(args: Array<String>) { launch(CommonPool) { delay(1000L) println("World!") } println("Hello,") Thread.sleep(2000L) } /* 運(yùn)行結(jié)果: ("Hello,"會(huì)立即被打印, 1000毫秒之后, "World!"會(huì)被打印) Hello, World! */
此處解釋一下delay方法:
在協(xié)程里delay方法作用等同于線程里的sleep, 都是休息一段時(shí)間, 但不同的是delay不會(huì)阻塞當(dāng)前線程, 而像是設(shè)置了一個(gè)鬧鐘, 在鬧鐘未響之前, 運(yùn)行該協(xié)程的線程可以被安排做了別的事情, 當(dāng)鬧鐘響起時(shí), 協(xié)程就會(huì)恢復(fù)運(yùn)行.
在Android中使用協(xié)程
在Android中使用協(xié)程需要引入如下兩個(gè)庫(kù):
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.1" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.1"
官方建議有生命周期的類(lèi)繼承 CoroutineSocpe,這樣就能讓全部協(xié)程跟著生命周期結(jié)束。
MainActivity : AppCompatActivity(), CoroutineScope by MainScope(){ override fun onDestroy(){ super.onDestory() cancel() } }
在村莊UI邏輯類(lèi)中使用:
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。下面我們來(lái)說(shuō)一下它們的一些區(qū)別:
- aunch 沒(méi)有返回值,或者說(shuō)返回只是 job ,能夠知道任務(wù)的狀態(tài),卻不能攜帶返回結(jié)果。
- async 有返回值,也就是返回的是 Deferred ,它是繼承的 job ,所有job有的,它都有,還具備了job沒(méi)有的攜帶數(shù)據(jù)回來(lái)的能力。
- launch 可以用來(lái)運(yùn)行不需要操作結(jié)果的協(xié)程(如文件刪除,創(chuàng)建等)
- async 可以用來(lái)運(yùn)行異步耗時(shí)任務(wù)并且需要返回值的任務(wù)(網(wǎng)絡(luò)請(qǐng)求,數(shù)據(jù)庫(kù)操作,文件讀寫(xiě)等)。
以下是Job和Deferred的生命周期說(shuō)明。
以下是一個(gè)使用示例:
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ò)請(qǐng)求.. getWebTime() } //do sth ... var value = deferred.await() //do sth... }
可以看到,我們使用了兩個(gè)新的東西Dispather和suspend。
Dispther可以理解為是一個(gè)協(xié)程調(diào)度器,用來(lái)調(diào)度協(xié)程跑到哪個(gè)線程中。Dispather 可以在 launch、async 等啟動(dòng)協(xié)程時(shí),指定在哪個(gè)線程里面運(yùn)行,也可以在協(xié)程中,使用 withContext(Dispather.) 來(lái)切換線程,使用 withContext 切換線程時(shí),有返回值。
Suspend是協(xié)程里面唯一一個(gè)修飾符,用來(lái)修改函數(shù)的,表明函數(shù)是一個(gè)掛起函數(shù),協(xié)程編譯器會(huì)在編譯期間進(jìn)行CPS變換,去做一些不可描述的事情。用suspend修飾的函數(shù),只能在協(xié)程體和同樣使用 suspend 修飾的函數(shù)中調(diào)用。
另外,我們還可以同時(shí)進(jìn)行多個(gè)網(wǎng)絡(luò)請(qǐng)求,并在全部請(qǐng)求完畢之后進(jìn)行數(shù)據(jù)整理,統(tǒng)一渲染界面,如下所示。
launch { var userInfoDeferred = async { //獲取用戶基本信息 getUserInfo(aid) } var userTeamsDeferred = async{ //獲取用戶團(tuán)隊(duì).. getUserTeams(aid) } var userOrgsDeferred = async { //獲取用戶組織機(jī)構(gòu) getUserOrgs(aid) } var userInfo = userInfoDeferred.await() var userTeams = userTeamsDeferred.await() var userOrgsDeferred = userOrgsDeferred.await() //渲染UI }
事實(shí)上,對(duì)于協(xié)程的簡(jiǎn)單理解與使用,協(xié)程到底是什么, 很難給出具體的定義, 就算能給出具體定義, 也會(huì)非常抽象難以理解的。另一方面, 協(xié)程可以說(shuō)是編譯器的能力, 因?yàn)閰f(xié)程并不需要操作系統(tǒng)和硬件的支持(線程需要), 是編譯器為了讓開(kāi)發(fā)者寫(xiě)代碼更簡(jiǎn)單方便, 提供了一些關(guān)鍵字, 并在內(nèi)部自動(dòng)生成了一些支持型代碼。
總的來(lái)說(shuō),協(xié)程就是一種輕量級(jí)的線程框架,它允許開(kāi)發(fā)者以順序的方式編寫(xiě)異步代碼。并且,相比傳統(tǒng)的 Handler 和 AsyncTask編程,協(xié)程能夠更好的利用系統(tǒng)資源,提高代碼的可讀性和可維護(hù)性。
以上就是Android 協(xié)程代替Handler使用示例詳解的詳細(xì)內(nèi)容,更多關(guān)于Android 協(xié)程代替Handler的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android多功能視頻播放器GSYVideoPlayer開(kāi)發(fā)流程
怎么在Android中實(shí)現(xiàn)GSYVideoPlayer視頻播放器?很多新手對(duì)此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來(lái)學(xué)習(xí)下,希望你能有所收獲2022-11-11Android圖片實(shí)現(xiàn)壓縮處理的實(shí)例代碼
本篇文章主要介紹了Android圖片實(shí)現(xiàn)壓縮處理的實(shí)例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-07-07Android貝塞爾曲線初步學(xué)習(xí)第二課 仿QQ未讀消息氣泡拖拽黏連效果
這篇文章主要為大家詳細(xì)介紹了Android貝塞爾曲線初步學(xué)習(xí)的第二課,仿QQ未讀消息氣泡拖拽黏連效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03Android中AlarmManager+Notification實(shí)現(xiàn)定時(shí)通知提醒功能
本篇文章主要介紹了Android中AlarmManager+Notification實(shí)現(xiàn)定時(shí)通知提醒功能,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2017-10-10Android編程實(shí)現(xiàn)兩個(gè)Activity之間共享數(shù)據(jù)及互相訪問(wèn)的方法
這篇文章主要介紹了Android編程實(shí)現(xiàn)兩個(gè)Activity之間共享數(shù)據(jù)及互相訪問(wèn)的方法,簡(jiǎn)單分析了Android中Activity數(shù)據(jù)共享與訪問(wèn)的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-11-11Flutter定義tabbar底部導(dǎo)航路由跳轉(zhuǎn)的方法
這篇文章主要為大家詳細(xì)介紹了Flutter定義tabbar底部導(dǎo)航路由跳轉(zhuǎn)的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-07-07Android實(shí)現(xiàn)日夜間模式的深入理解
相信Android的日間/夜間模式切換相信大家在平時(shí)使用 APP 的過(guò)程中都遇到過(guò),比如知乎、簡(jiǎn)書(shū)中就有相關(guān)的模式切換。實(shí)現(xiàn)日間/夜間模式切換的方案也有許多種,趁著今天有空來(lái)講一下日間/夜間模式切換的幾種實(shí)現(xiàn)方案,也可以做一個(gè)橫向的對(duì)比來(lái)看看哪種方案最好。2016-09-09Android進(jìn)階CoordinatorLayout協(xié)調(diào)者布局實(shí)現(xiàn)吸頂效果
這篇文章主要為大家介紹了Android進(jìn)階CoordinatorLayout協(xié)調(diào)者布局實(shí)現(xiàn)吸頂效果,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01android初學(xué)者必須掌握的Activity狀態(tài)的四大知識(shí)點(diǎn)(必讀)
本篇文章主要介紹了android activity的四種狀態(tài),詳細(xì)的介紹了四種狀態(tài),包括Running狀態(tài)、Paused狀態(tài)、Stopped狀態(tài)、Killed狀態(tài),有興趣的可以了解一下。2016-11-11