簡體   English   中英

合並來自 Kotlin Flow/LiveData 的數據

[英]Combine data from Kotlin Flow/LiveData

我的存儲庫中有一個看起來像這樣的流程:

val userListFlow: Flow<List<User>> = channelFlow<List<User>> {
        source.setOnUserUpdatedListener { userList ->
           trySend(userList)
        }
        awaitClose {
            logger.info("waitClose")
            source.setOnUserUpdatedListener(null)
        }
    }.stateIn(
       scope = externalScope,
       started = SharingStarted.WhileSubscribed(5000),
       initialValue = emptyList()
   )


 suspend fun getUserThumbnail(user: User): File {
    return getUserThumbFromCache(user) ?: run {
       fetchUserThumbnailRemote()
    }
 } 

 private suspend fetchUserThumbnailRemote(user: User): Bitmap {
    thumbnailService.getUserThumbnailBitmap(user.id)
 }

 fun getUserThumbFromCache(user: User) {
    val thumbFile = getThumbFile(user)
    return if (thumbFile.exists() && thumbFile.size() > 0) {
      thumbFile
    } else null
 }

 private fun getThumbFile(user: User): File {
   return File(cacheDir, "${user.id}.jpg")
 }
}

對於這些用戶中的每一個,我可以調用暫停 function 來獲取用戶的縮略圖。 我不想在顯示用戶列表之前等待縮略圖,我寧願它顯示用戶,然后在獲取縮略圖時更新列表。

但是,我希望在獲取縮略圖時更新列表..

從我的 ViewModel 我有類似的東西

  data class UserWithThumb(user: User, thumb: File?)


  val userLiveData = repo.userListFlow.map {
      UserWithThumb(it, repo.getUserThumbFromCache(it))
  }.asLiveData()

那么從我的 Fragment 我做

 viewModel.userLiveData.observe(viewLifecycleOwner) {
       userListAdapter.submitList(it)
 }

我的縮略圖都是 null 雖然我需要從遠程獲取它們。 但是,如果我將其稱為 function,那么這將延遲我的列表到達 UI,直到獲取縮略圖。 如何以干凈的方式獲取 UI 的縮略圖? 我意識到,一旦獲取縮略圖,我需要讓我的 livedata 或流自行更新,但我不知道如何將其掛鈎到我的代碼中。 任何想法,將不勝感激。

我想考慮這個問題的一種方法是我希望我的上游(存儲庫)流包含用戶列表,但是我想更新給視圖的列表,而不僅僅是當上游(repo)流變得新時數據,但是當新的縮略圖也被下載時..

我從這個問題中了解到的是,您有一個UserWithThumb列表,一旦您設置了User的列表,並且您想立即將其顯示給 UI,就會創建該列表。 在后台你想獲取用戶縮略圖,一旦你收到它們,你想再次更新列表。

實現您想要的一種方法是:

val userLiveData = flow {
    repo.userListFlow.collect { users ->
        val initialList = users.map { UserWithThumb(it, repo. getUserThumbFromCache(it)) }
        emit(initialList)
        coroutineScope {
            val finalList = users.map {
                async(Dispatchers.IO) {  // fetch all thumbnails in parallel
                    UserWithThumb(it, repo. getUserThumbnail(it))
                }
            }.awaitAll() // wait until all thumbnails have been fetched
            emit(finalList)
        } 
    }
}.asLiveData()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM