Android協(xié)程代替Handler使用示例詳解
引言
在 Android 開發(fā)中,我們經(jīng)常需要處理異步任務,例如網(wǎng)絡請求、數(shù)據(jù)庫訪問、耗時計算等等。為了在處理異步任務時能夠方便地更新 UI,Android 提供了 Handler 類。然而,在使用 Handler 時,我們需要處理一些繁瑣的問題,例如線程間通信和內(nèi)存泄漏。為了簡化這些問題,Google 在 Android 3.0 引入了 AsyncTask 類,但它仍然有一些限制。最近,Kotlin 官方推出了 Kotlin 協(xié)程,它是一種輕量級的線程框架,可以在 Android 開發(fā)中替代 Handler 和 AsyncTask,并提供更加簡潔和強大的異步編程體驗。
什么是協(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ù)或者復雜的線程管理代碼。
- 避免回調(diào)地獄:使用協(xié)程,我們可以將異步任務的邏輯寫在一個連續(xù)的代碼塊中,而不是多個回調(diào)函數(shù)中,提高代碼的可讀性和可維護性。
- 更好的錯誤處理:協(xié)程提供了異常處理機制,可以很方便地捕獲和處理異步任務中的異常。
- 更好的性能:協(xié)程使用非阻塞的方式執(zhí)行異步任務,可以更好地利用系統(tǒng)資源,提高應用的性能。
- 更好的 UI 交互:協(xié)程允許我們在主線程中執(zhí)行異步任務,從而方便地更新 UI。
使用協(xié)程代替 Handler
在 Android 中,我們經(jīng)常需要在子線程中執(zhí)行一些耗時的任務,然后在主線程中更新 UI。使用 Handler,我們可以很方便地實現(xiàn)這個功能。然而,使用 Handler 時,我們需要處理一些繁瑣的問題,例如線程間通信和內(nèi)存泄漏。現(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í)行一些異步任務。
下面是官方一個使用協(xié)程替代 Handler 的示例代碼:
fun main(args: Array<String>) { launch(CommonPool) { delay(1000L) println("World!") } println("Hello,") Thread.sleep(2000L) } /* 運行結(jié)果: ("Hello,"會立即被打印, 1000毫秒之后, "World!"會被打印) Hello, World! */
此處解釋一下delay方法:
在協(xié)程里delay方法作用等同于線程里的sleep, 都是休息一段時間, 但不同的是delay不會阻塞當前線程, 而像是設置了一個鬧鐘, 在鬧鐘未響之前, 運行該協(xié)程的線程可以被安排做了別的事情, 當鬧鐘響起時, 協(xié)程就會恢復運行.
在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() } }
運行協(xié)程
Android有兩種運行協(xié)程,分別是launch與async。下面我們來說一下它們的一些區(qū)別:
- aunch 沒有返回值,或者說返回只是 job ,能夠知道任務的狀態(tài),卻不能攜帶返回結(jié)果。
- async 有返回值,也就是返回的是 Deferred ,它是繼承的 job ,所有job有的,它都有,還具備了job沒有的攜帶數(shù)據(jù)回來的能力。
- launch 可以用來運行不需要操作結(jié)果的協(xié)程(如文件刪除,創(chuàng)建等)
- async 可以用來運行異步耗時任務并且需要返回值的任務(網(wǎng)絡請求,數(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)絡請求.. getWebTime() } //do sth ... var value = deferred.await() //do sth... }
可以看到,我們使用了兩個新的東西Dispather和suspend。
Dispther可以理解為是一個協(xié)程調(diào)度器,用來調(diào)度協(xié)程跑到哪個線程中。Dispather 可以在 launch、async 等啟動協(xié)程時,指定在哪個線程里面運行,也可以在協(xié)程中,使用 withContext(Dispather.) 來切換線程,使用 withContext 切換線程時,有返回值。
Suspend是協(xié)程里面唯一一個修飾符,用來修改函數(shù)的,表明函數(shù)是一個掛起函數(shù),協(xié)程編譯器會在編譯期間進行CPS變換,去做一些不可描述的事情。用suspend修飾的函數(shù),只能在協(xié)程體和同樣使用 suspend 修飾的函數(shù)中調(diào)用。
另外,我們還可以同時進行多個網(wǎng)絡請求,并在全部請求完畢之后進行數(shù)據(jù)整理,統(tǒng)一渲染界面,如下所示。
launch { var userInfoDeferred = async { //獲取用戶基本信息 getUserInfo(aid) } var userTeamsDeferred = async{ //獲取用戶團隊.. getUserTeams(aid) } var userOrgsDeferred = async { //獲取用戶組織機構(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)資源,提高代碼的可讀性和可維護性。
以上就是Android 協(xié)程代替Handler使用示例詳解的詳細內(nèi)容,更多關(guān)于Android 協(xié)程代替Handler的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android多功能視頻播放器GSYVideoPlayer開發(fā)流程
怎么在Android中實現(xiàn)GSYVideoPlayer視頻播放器?很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲2022-11-11Android貝塞爾曲線初步學習第二課 仿QQ未讀消息氣泡拖拽黏連效果
這篇文章主要為大家詳細介紹了Android貝塞爾曲線初步學習的第二課,仿QQ未讀消息氣泡拖拽黏連效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-03-03Android中AlarmManager+Notification實現(xiàn)定時通知提醒功能
本篇文章主要介紹了Android中AlarmManager+Notification實現(xiàn)定時通知提醒功能,非常具有實用價值,需要的朋友可以參考下2017-10-10Android編程實現(xiàn)兩個Activity之間共享數(shù)據(jù)及互相訪問的方法
這篇文章主要介紹了Android編程實現(xiàn)兩個Activity之間共享數(shù)據(jù)及互相訪問的方法,簡單分析了Android中Activity數(shù)據(jù)共享與訪問的相關(guān)技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-11-11Flutter定義tabbar底部導航路由跳轉(zhuǎn)的方法
這篇文章主要為大家詳細介紹了Flutter定義tabbar底部導航路由跳轉(zhuǎn)的方法,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-07-07Android進階CoordinatorLayout協(xié)調(diào)者布局實現(xiàn)吸頂效果
這篇文章主要為大家介紹了Android進階CoordinatorLayout協(xié)調(diào)者布局實現(xiàn)吸頂效果,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-01-01android初學者必須掌握的Activity狀態(tài)的四大知識點(必讀)
本篇文章主要介紹了android activity的四種狀態(tài),詳細的介紹了四種狀態(tài),包括Running狀態(tài)、Paused狀態(tài)、Stopped狀態(tài)、Killed狀態(tài),有興趣的可以了解一下。2016-11-11