国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

[譯] 在 Android 使用協程(part III) - 在實際工作中使用

番茄西紅柿 / 1735人閱讀

摘要:通過實現一次請求來解釋使用協程中的實際問題是這篇文章的重點。當接收一個新事件時,啟動一個新的協程來對列表進行排序,并在響應時更新。在中啟動協程作為一般模式。因此,在默認情況下,在存儲庫中啟動的任何協程都會泄露。


原文鏈接:Coroutines On Android (part III): Real work

原文作者:Sean McQuillan

這是一篇關于在 Android 上使用協程的系列文章之一。通過實現一次請求來解釋使用協程中的實際問題是這篇文章的重點。

本系列的其他文章:

[譯] 在 Android 使用協程(part I) - 協程的背景知識

[譯] 在 Android 使用協程(part II) - 入門指南

使用協程解決實際問題

本系列的第 1 部分和第 2 部分重點介紹了如何使用協程來簡化代碼、在 Android 上提供主線程安全調用以及避免協程泄露。有了這個背景,協程看起來是一個既可以用于后臺處理,又可以簡化 Callback 的很好解決方案。

到目前為止,我們主要關注的是「什么是協程」以及「如何管理它們」。在這篇文章中,我們將看看如何使用它們來完成一些真正的任務。協程是一種通用的編程語言特性,與函數處于同一級別,因此,你可以使用它們來實現任何使用函數和對象實現的功能。然而,有兩種類型的任務總是出現在實際代碼中,協程是一種很好的解決方案:

    一次性請求 它們總是在得到響應時認為請求完成了,所以每次調用時都會重新運行的請求

    流請求 它們不會在得到第一個響應時就認為請求完成了,還會繼續觀察改變并將其報告給調用者

協程是這兩個任務的一個很好的解決方案。在這篇文章中,我們將深入研究一次性請求,并探索如何在 Android 上用協程實現它們。

一次性請求

每次調用一個一次性請求都會執行一次,并在響應時完成。此模式與常規函數調用相同——被調用,執行一些操作,然后返回。由于與函數調用的相似性,它們往往比流請求更容易理解。

每次調用一個一次性請求時都會執行一次。一旦得到響應,就停止執行。

對于一次性請求的示例,請考慮瀏覽器如何加載此頁面。當你點擊到這篇文章的鏈接時,瀏覽器向服務器發送了一個網絡請求來加載頁面。一旦頁面被傳輸到你的瀏覽器,它就停止與后端通信——它已經獲取到需要的所有數據。如果服務器修改了這篇文章,除非你刷新頁面否則新的修改將不會顯示在瀏覽器中。

因此,雖然它們缺乏流請求的實時推送功能,但一次性請求仍舊非常強大。在 Android 應用中,有很多事情可以通過一次性請求來解決,比如獲取、存儲或更新數據。對于排序列表之類的事情,它也是一種很好的模式。

問題:顯示已排序的列表

讓我們通過查看如何顯示排序列表來研究一次性請求。為了讓示例更加具體,我們構建了一個「存貨清單」的應用,供商店員工使用。它將用于根據產品最后一次進貨的時間查找產品——他們希望能夠對列表進行升序和降序排序。因為有很多產品,排序產品可能需要一秒鐘,所以我們將使用協程來避免阻塞主線程!

在這個應用中,所有的產品都存儲在一個 Room 數據庫中。這是一個很好的用例,因為它不需要涉及網絡請求,所以我們可以關注模式。盡管這個示例比較簡單,因為它不使用網絡,但是它展示了實現一次性請求所需的模式。

要使用協程實現這個請求,你將把協程引入到 ViewModel、Repository 和 Dao。讓我們逐個瀏覽一下,看看如何將它們與協程集成在一起。

class ProductsViewModel(val productsRepository: ProductsRepository): ViewModel() {
   val _sortedProducts = MutableLiveData>()
   val sortedProducts: LiveData> = _sortedProducts

   /**
    * 當用戶點擊 sort 按鈕時調用,由 UI 層調用
    */
   fun onSortAscending() = sortPricesBy(ascending = true)
   fun onSortDescending() = sortPricesBy(ascending = false)

   private fun sortPricesBy(ascending: Boolean) {
       viewModelScope.launch {
           // 掛起和恢復使這個數據庫請求確保主線程安全
           // 所以我們的 ViewModel 不需要擔心線程
           _sortedProducts.value =
                   productsRepository.loadSortedProducts(ascending)
       }
   }
}

ProductsViewModel 負責從 UI 層接收事件,然后向存儲庫請求更新后的數據。它使用 LiveData 保存當前已排序的列表,以便讓 UI 顯示。當 sortProductsBy 接收一個新事件時,啟動一個新的協程來對列表進行排序,并在響應時更新 LiveData。ViewModel 通常是這個體系結構中啟動大多數協程的正確位置,因為它可以在 onCleared中取消協程。如果用戶離開界面,它們通常不再需要工作。

如果你還不經常使用 LiveData,請查看 @CeruleanOtter發布的這篇很棒的文章,它介紹了如何為 UI 存儲數據.

一個簡單的 ViewModel 示例 (ViewModels : A Simple Example)

這是 Android 上協程的一般模式。由于 Android 框架不能調用掛起函數,因此你需要配合一個協程來響應 UI 事件。最簡單的辦法是事件發生時啟動一個新的協程,而在 ViewModel 做這件事比較合適。

在 ViewModel 中啟動協程作為一般模式。

ViewModel 使用 ProductsRepository 來實際獲取數據。來看它是這樣做的:

class ProductsRepository(val productsDao: ProductsDao) {

  /**
    * 這是一個"常規"掛起函數,這意味著調用者必須處于一個協程中。存儲層不負責啟動或
    * 停止協程,因為它沒有一個合適的生命周期來取消不必要的工作。
    * 這可以是從 Dispatchers.Main 調用的,而且是主線程安全的,因為 Room 將為我們負責
    * 主線程安全。
    */
   suspend fun loadSortedProducts(ascending: Boolean): List {
       return if (ascending) {
           productsDao.loadProductsByDateStockedAscending()
       } else {
           productsDao.loadProductsByDateStockedDescending()
       }
   }
}

ProductsRepository 為產品交互提供了一個合理的接口。在這個應用程序中,由于所有內容都在本地的 Room 數據庫中,所以他只是為 @Dao 提供了一個很好的接口,對于不同的排序,@Dao 有兩個不同的函數。

存儲層是 Android 架構體系中一個可選部分——但如果你的應用有它或類似的層,它應該更愿意暴露常規掛起函數。因為存儲層沒有一個天然的生命周期——它只是一個對象——它沒有辦法清理工作。因此,在默認情況下,在存儲庫中啟動的任何協程都會泄露。

除了避免泄露之外,通過暴露常規掛起函數,還可以很容易地在不同的上下文中復用存儲庫。任何知道如何創造協程的東西都可以調用 loadSortedProducts 。例如,Workmanager 調度的后臺 Job 可以直接調用它。

存儲庫應該暴露出主線程安全的常規掛起函數。

注意:一些后臺保存操作可能會希望用戶離開界面后繼續執行——在沒有生命周期的情況下運行這些保存是有意義的。在大多數其他情況下,viewModelScope 是一個合理的選擇。

繼續看 ProductsDao,它看起來是這樣的:

@Dao
interface ProductsDao {
   // 因為這是掛起的,Room 將使用它自己的調度器以主線程安全的方式運行這個查詢
   @Query("select * from ProductListing ORDER BY dateStocked ASC")
   suspend fun loadProductsByDateStockedAscending(): List

   // 因為這是掛起的,Room 將使用它自己的調度器以主線程安全的方式運行這個查詢
   @Query("select * from ProductListing ORDER BY dateStocked DESC")
   suspend fun loadProductsByDateStockedDescending(): List
}  

ProductsDao 是一個 Room @Dao ,它公開了兩個掛起函數。由于函數被suspend 標記,Room 確保它們是主線程安全的。這意味著你可以直接從 Dispatchers.Main 來調用它們。

如果你還沒有在 Room 中看到協程,請查看 @FMuntenescu的這篇很棒的文章

Room

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/7055.html

相關文章

  • [] WorkManager 基礎入門

    摘要:讓我們探討一下如何確保你的工作脫離主線程運行并保證執行。這確保在默認情況下,你的工作是同步運行的,并且在主線程之外運行。這是應該脫離主線程運行的工作,但是,因為它與直接相關,所以如果關閉應用程序則不需要繼續。 原文地址:WorkManager Basics 原文作者:Lyla Fujiwara 譯文出自:掘金翻譯計劃 本文永久鏈接:github.com/xitu/gold-m… 譯者:Ri...

    番茄西紅柿 評論0 收藏0
  • []教程:如何使用Rollup打包樣式文件并添加LiveReload

    摘要:通過這個教程學習如何使用打包工具配合來取代或處理樣式文件。使用這個命令安裝插件更新。如果你沒有項目的副本,你可以通過這條命令克隆在結束這個狀態下的項目為添加監聽插件。在代碼塊內,添加如下內容簡單起見我省略了文件的大部分內容 通過這個教程學習如何使用JavaScript打包工具Rollup配合PostCSS來取代Grunt或Gulp處理樣式文件。 上一篇文章中,我們完成了使用Rollup...

    garfileo 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<