最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用kotlin協(xié)程提高app性能(譯)

 更新時間:2019年12月25日 09:34:42   作者:Carve_Time  
這篇文章主要介紹了使用kotlin協(xié)程提高app性能(譯),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

協(xié)程是一種并發(fā)設計模式,您可以在Android上使用它來簡化異步執(zhí)行的代碼。Kotlin1.3版本添加了 Coroutines,并基于其他語言的既定概念。

在Android上,協(xié)程有助于解決兩個主要問題:

  • 管理長時間運行的任務,否則可能會阻止主線程并導致應用凍結。
  • 提供主安全性,或從主線程安全地調用網(wǎng)絡或磁盤操作。

本主題描述了如何使用Kotlin協(xié)程解決這些問題,使您能夠編寫更清晰,更簡潔的應用程序代碼。

管理長時間運行的任務

在Android上,每個應用程序都有一個主線程來處理用戶界面并管理用戶交互。如果您的應用程序為主線程分配了太多工作,那么應用程序可能會明顯卡頓或運行緩慢。網(wǎng)絡請求,JSON解析,從數(shù)據(jù)庫讀取或寫入,甚至只是迭代大型列表都可能導致應用程序運行緩慢,導致可見的緩慢或凍結的UI對觸摸事件響應緩慢。這些長時間運行的操作應該在主線程之外運行。

以下示例顯示了假設的長期運行任務的簡單協(xié)程實現(xiàn):

suspend fun fetchDocs() {        // Dispatchers.Main
 val result = get("https://developer.android.com") // Dispatchers.IO for `get`
 show(result)          // Dispatchers.Main
}

suspend fun get(url: String) = withContext(Dispatchers.IO) { /* ... */ }

協(xié)同程序通過添加兩個操作來處​​理長時間運行的任務,從而構建常規(guī)功能。除了invoke(或call)和返回之外,協(xié)同程序還添加了suspend和resume:

  • suspend暫停當前協(xié)同程序的執(zhí)行,保存所有局部變量。
  • resume恢復從暫停的協(xié)同處繼續(xù)執(zhí)行暫停的協(xié)同程序。

您只能從其他suspend函數(shù)調用suspend函數(shù),或者使用諸如啟動之類的協(xié)程構建器來啟動新的協(xié)程。

在上面的示例中,get()仍然在主線程上運行,但它在啟動網(wǎng)絡請求之前掛起協(xié)同程序。當網(wǎng)絡請求完成時,get恢復暫停的協(xié)程,而不是使用回調來通知主線程。

Kotlin使用堆棧框架來管理與任何局部變量一起運行的函數(shù)。掛起協(xié)程時,將復制并保存當前堆棧幀以供以后使用?;謴蜁r,堆棧幀將從保存位置復制回來,并且該函數(shù)將再次開始運行。即使代碼看起來像普通的順序阻塞請求,協(xié)程也可以確保網(wǎng)絡請求避免阻塞主線程。

Use coroutines for main-safety

Kotlin協(xié)程使用調度程序來確定哪些線程用于協(xié)程執(zhí)行。要在主線程之外運行代碼,您可以告訴Kotlin協(xié)程在Default或IO調度程序上執(zhí)行工作。在Kotlin中,所有協(xié)同程序必須在調度程序中運行,即使它們在主線程上運行。協(xié)同程序可以暫停,調度程序負責恢復它們。
要指定協(xié)程應該運行的位置,Kotlin提供了三個可以使用的調度程序:

  • Dispatchers.Main  - 使用此調度程序在主Android線程上運行協(xié)同程序。 這應該僅用于與UI交互并執(zhí)行快速工作。 示例包括調用掛起函數(shù),運行Android UI框架操作以及更新LiveData對象。
  • Dispatchers.IO  - 此調度程序已經(jīng)過優(yōu)化,可在主線程外執(zhí)行磁盤或網(wǎng)絡I / O. 示例包括使用Room組件,讀取或寫入文件以及運行任何網(wǎng)絡操作。
  • Dispatchers.Default  - 此調度程序已經(jīng)過優(yōu)化,可以在主線程之外執(zhí)行CPU密集型工作。 示例用例包括對列表進行排序和解析JSON。

繼續(xù)前面的示例,您可以使用調度程序重新定義get函數(shù)。 在get的主體內部,調用withContext(Dispatchers.IO)來創(chuàng)建一個在IO線程池上運行的塊。 放在該塊中的任何代碼總是通過IO調度程序執(zhí)行。 由于withContext本身是一個掛起函數(shù),因此函數(shù)get也是一個掛起函數(shù)。

使用協(xié)同程序,您可以調度具有細粒度控制的線程。 因為withContext()允許您控制任何代碼行的線程池而不引入回調,所以您可以將它應用于非常小的函數(shù),例如從數(shù)據(jù)庫讀取或執(zhí)行網(wǎng)絡請求。 一個好的做法是使用withContext()來確保每個函數(shù)都是主安全的,這意味著您可以從主線程調用該函數(shù)。 這樣,調用者永遠不需要考慮應該使用哪個線程來執(zhí)行該函數(shù)。

在前面的示例中,fetchDocs()在主線程上執(zhí)行; 但是,它可以安全地調用get,后者在后臺執(zhí)行網(wǎng)絡請求。 因為協(xié)同程序支持掛起和恢復,所以只要withContext塊完成,主線程上的協(xié)程就會以get結果恢復。

重要說明:使用suspend并不能告訴Kotlin在后臺線程上運行函數(shù)。 暫停函數(shù)在主線程上運行是正常的。 在主線程上啟動協(xié)同程序也很常見。 當您需要主安全時,例如在讀取或寫入磁盤,執(zhí)行網(wǎng)絡操作或運行CPU密集型操作時,應始終在掛起函數(shù)內使用withContext()。

與等效的基于回調的實現(xiàn)相比,withContext()不會增加額外的開銷。 此外,在某些情況下,可以優(yōu)化withContext()調用,而不是基于等效的基于回調的實現(xiàn)。 例如,如果一個函數(shù)對網(wǎng)絡進行十次調用,則可以通過使用外部withContext()告訴Kotlin只切換一次線程。 然后,即使網(wǎng)絡庫多次使用withContext(),它仍然停留在同一個調度程序上,并避免切換線程。 此外,Kotlin優(yōu)化了Dispatchers.Default和Dispatchers.IO之間的切換,以盡可能避免線程切換。

要點:使用使用Dispatchers.IO或Dispatchers.Default等線程池的調度程序并不能保證該塊從上到下在同一個線程上執(zhí)行。 在某些情況下,Kotlin協(xié)程可能會在暫停和恢復后將執(zhí)行移動到另一個線程。 這意味著線程局部變量可能不會指向整個withContext()塊的相同值。

指定CoroutineScope

定義協(xié)程時,還必須指定其CoroutineScope。 CoroutineScope管理一個或多個相關協(xié)程。 您還可以使用CoroutineScope在該范圍內啟動新協(xié)程。 但是,與調度程序不同,CoroutineScope不會運行協(xié)同程序。

CoroutineScope的一個重要功能是當用戶離開應用程序中的內容區(qū)域時停止協(xié)程執(zhí)行。 使用CoroutineScope,您可以確保正確停止任何正在運行的操作。

將CoroutineScope與Android架構組件配合使用

在Android上,您可以將CoroutineScope實現(xiàn)與組件生命周期相關聯(lián)。這樣可以避免泄漏內存或為與用戶不再相關的activity或fragment執(zhí)行額外的工作。使用Jetpack組件,它們自然適合ViewModel。由于ViewModel在配置更改(例如屏幕旋轉)期間不會被銷毀,因此您不必擔心協(xié)同程序被取消或重新啟動。

范圍知道他們開始的每個協(xié)同程序。這意味著您可以隨時取消在作用域中啟動的所有內容。范圍傳播自己,所以如果一個協(xié)程開始另一個協(xié)同程序,兩個協(xié)同程序具有相同的范圍。這意味著即使其他庫從您的范圍啟動協(xié)程,您也可以隨時取消它們。如果您在ViewModel中運行協(xié)同程序,這一點尤為重要。如果因為用戶離開了屏幕而導致ViewModel被銷毀,則必須停止它正在執(zhí)行的所有異步工作。否則,您將浪費資源并可能泄漏內存。如果您在銷毀ViewModel后應該繼續(xù)進行異步工作,則應該在應用程序架構的較低層中完成。

警告:通過拋出CancellationException協(xié)同取消協(xié)同程序。 在協(xié)程取消期間觸發(fā)捕獲異?;騎hrowable的異常處理程序。

使用適用于Android體系結構的KTX庫組件,您還可以使用擴展屬性viewModelScope來創(chuàng)建可以運行的協(xié)同程序,直到ViewModel被銷毀。

啟動一個協(xié)程

您可以通過以下兩種方式之一啟動協(xié)同程序:

  • launch會啟動一個新的協(xié)程,并且不會將結果返回給調用者。 任何被認為是“發(fā)射并忘記”的工作都可以使用launch來開始。
  • async啟動一個新的協(xié)同程序,并允許您使用名為await的掛起函數(shù)返回結果。

通常,您應該從常規(guī)函數(shù)啟動新協(xié)程,因為常規(guī)函數(shù)無法調用等待。 僅在另一個協(xié)同程序內部或在掛起函數(shù)內部執(zhí)行并行分解時才使用異步。

在前面的示例的基礎上,這里是一個帶有viewModelScope KTX擴展屬性的協(xié)程,它使用launch從常規(guī)函數(shù)切換到協(xié)同程序:

fun onDocsNeeded() {
 viewModelScope.launch { // Dispatchers.Main
  fetchDocs()   // Dispatchers.Main (suspend function call)
 }
}

警告:啟動和異步處理異常的方式不同。 由于async期望在某個時刻最終調用await,它會保留異常并在await調用中重新拋出它們。 這意味著如果您使用await從常規(guī)函數(shù)啟動新的協(xié)同程序,則可能會以靜默方式刪除異常。 這些丟棄的異常不會出現(xiàn)在崩潰指標中,也不會出現(xiàn)在logcat中。

并行分解

當函數(shù)返回時,必須停止由掛起函數(shù)啟動的所有協(xié)同程序,因此您可能需要保證這些協(xié)程在返回之前完成。 通過Kotlin中的結構化并發(fā),您可以定義一個啟動一個或多個協(xié)同程序的coroutineScope。 然后,使用await()(對于單個協(xié)同程序)或awaitAll()(對于多個協(xié)程),可以保證這些協(xié)程在從函數(shù)返回之前完成。

例如,讓我們定義一個以異步方式獲取兩個文檔的coroutineScope。 通過在每個延遲引用上調用await(),我們保證在返回值之前兩個異步操作都完成:

suspend fun fetchTwoDocs() =
 coroutineScope {
  val deferredOne = async { fetchDoc(1) }
  val deferredTwo = async { fetchDoc(2) }
  deferredOne.await()
  deferredTwo.await()
 }

即使fetchTwoDocs()使用異步啟動新的協(xié)同程序,該函數(shù)也會使用awaitAll()等待那些啟動的協(xié)同程序在返回之前完成。 但請注意,即使我們沒有調用awaitAll(),coroutineScope構建器也不會恢復調用fetchTwoDocs的協(xié)程,直到所有新的協(xié)程完成。

此外,coroutineScope捕獲協(xié)程拋出的任何異常并將它們路由回調用者。

有關并行分解的更多信息,請參閱編寫掛起函數(shù)。

具有內置支持的架構組件

一些體系結構組件(包括ViewModel和Lifecycle)通過其自己的CoroutineScope成員包含對協(xié)同程序的內置支持。
例如,ViewModel包含一個內置的viewModelScope。 這提供了在ViewModel范圍內啟動協(xié)同程序的標準方法,如以下示例所示:

class MyViewModel : ViewModel() {

 fun launchDataLoad() {
  viewModelScope.launch {
   sortList()
   // Modify UI
  }
 }

 /**
 * Heavy operation that cannot be done in the Main Thread
 */
 suspend fun sortList() = withContext(Dispatchers.Default) {
  // Heavy work
 }
}

LiveData還使用帶有l(wèi)iveData塊的協(xié)同程序:
liveData {
 // runs in its own LiveData-specific scope
}

原文

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • Android如何防止多次點擊事件

    Android如何防止多次點擊事件

    大家都遇到這樣一個問題吧,一個點擊事件多次觸發(fā)導致同樣的內容提交了很多次,下面小編給大家?guī)硪黄恼聨椭蠹医鉀Qandroid如何防止多次點擊事件,對android防止多次點擊事件相關只是感興趣的朋友一起學習吧
    2015-12-12
  • Android實現(xiàn)圖片滾動和頁簽控件功能的實現(xiàn)代碼

    Android實現(xiàn)圖片滾動和頁簽控件功能的實現(xiàn)代碼

    這篇文章主要介紹了Android實現(xiàn)圖片滾動控件含頁簽功能的實現(xiàn)代碼,具有很好的參考價值,希望對大家有所幫助,一起跟隨小編過來看看吧
    2018-05-05
  • Android實現(xiàn)未讀消息小紅點顯示實例

    Android實現(xiàn)未讀消息小紅點顯示實例

    大家好,本篇文章主要講的是Android實現(xiàn)未讀消息小紅點顯示實例,感興趣的同學趕快來看一看吧,對你有幫助的話記得收藏一下
    2022-02-02
  • 詳解Android代碼混淆實戰(zhàn)

    詳解Android代碼混淆實戰(zhàn)

    這篇文章主要介紹了詳解Android代碼混淆實戰(zhàn),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-08-08
  • 淺扒Android動態(tài)設置字體大小的示例

    淺扒Android動態(tài)設置字體大小的示例

    本篇文章主要介紹了淺扒Android動態(tài)設置字體大小的示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-12-12
  • Android仿iOS實現(xiàn)側滑返回功能(類似微信)

    Android仿iOS實現(xiàn)側滑返回功能(類似微信)

    這篇文章主要為大家詳細介紹了Android仿iOS實現(xiàn)側滑返回功能,類似微信功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-12-12
  • Flutter繪圖組件之CustomPaint使用詳解

    Flutter繪圖組件之CustomPaint使用詳解

    CustomPaint是Flutter中用于自由繪制的一個widget,它與android原生的繪制規(guī)則基本一致,以當前Canves(畫布)的左上角為原點進行繪制。本文將詳細講解CustomPaint的使用教程,需要的可以參考一下
    2022-03-03
  • RecyclerView自定義分割線

    RecyclerView自定義分割線

    這篇文章主要為大家詳細介紹了RecyclerView自定義分割線的相關資料,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-09-09
  • androidx下的fragment的lazy懶加載問題詳解

    androidx下的fragment的lazy懶加載問題詳解

    這篇文章主要介紹了androidx下的fragment的lazy懶加載問題詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-04-04
  • Android編程獲取網(wǎng)絡連接方式及判斷手機卡所屬運營商的方法

    Android編程獲取網(wǎng)絡連接方式及判斷手機卡所屬運營商的方法

    這篇文章主要介紹了Android編程獲取網(wǎng)絡連接方式及判斷手機卡所屬運營商的方法,涉及Android針對網(wǎng)絡的判斷及本機信息的獲取技巧,需要的朋友可以參考下
    2016-01-01

最新評論

通渭县| 那坡县| 涟源市| 西峡县| 全南县| 深圳市| 滦平县| 察隅县| 仙桃市| 余姚市| 巴楚县| 东丰县| 双桥区| 信丰县| 湘潭市| 山东| 盖州市| 汕尾市| 延庆县| 克山县| 北碚区| 玛曲县| 顺平县| 康平县| 杭州市| 砚山县| 峨边| 普洱| 油尖旺区| 石渠县| 台北市| 永胜县| 西乌| 卓尼县| 犍为县| 定西市| 乐东| 保山市| 蒲江县| 泗水县| 南平市|