我正在嘗試更新 Kotlin 中 Flow 的來源,但我不確定這是否是正確的方法,以及 Flow 是否可行。
我有一個包含用戶帖子的資料庫,這會回傳一個Flow<List<Post>>. 現在,當我選擇另一個用戶時,我希望資料庫流向我回傳新選擇用戶的帖子:
lateinit var userPosts: Flow<List<Post>>
private set
fun getPostsForUser(user: User) {
userPosts = database.getAllPostsForUser(user)
}
但是流永遠不會使用新選定用戶的資料進行更新。在這種情況下 Flow 是否仍然是正確的選擇,如果是,我如何使用新帖子更新流程?
我知道如何通過從資料庫中獲取資料并使用 LiveData 發出它來手動執行此操作,但是我想避免每次用戶發布新內容或洗掉帖子時處理帖子的更新。
uj5u.com熱心網友回復:
我想也許您正在收集一個流,然后設定一個用戶,這會更改屬性中的流,但不會更改已收集的任何現有的先前流。我不知道如何解釋正在發生的事情。
如果公共 Flow 屬性依賴于其他一些接受引數的函式,則可能容易出錯。您可以直接從函式回傳一個 Flow,因此行為沒有歧義。該片段請求特定用戶的流并立即獲取它。
distinctUntilChanged() 將阻止它發出由于 repo 中的其他更改而導致的未更改串列。
fun getPostsForUser(user: User) Flow<List<Post>> =
database.getAllPostsForUser(user).distinctUntilChanged()
如果您確實想使用您的模式,我認為您可以這樣做。這允許只有一個 Flow,因此盡早開始收集它是安全的。更改用戶將更改其發布的值。雖然這比上面更復雜,但它的優點是不需要在螢屏旋轉和其他配置更改時重繪 資料。
private val mutableUserPosts = MutableStateFlow<List<Post>>(emptyList())
val userPosts: Flow<List<Post>> = mutableUserPosts
private var userPostsJob: Job? = null
var user: User? = null
set(value) {
field = value
userPostsJob?.cancel()
value ?: return
userPostsJob = database.getAllPostsForUser(value)
.onEach { mutableUserPosts.emit(it) }
.launchIn(viewModelScope)
}
或者正如 Joffrey 所建議的那樣,如果您不介意使用不穩定的 API 函式,那么使用用戶流會更簡單flatMapLatest。user如果您不介意公開應在外部設定值的公共可變流,則可以洗掉此處的屬性。或者,如果您重復使用此模式,您可以為 StateFlow/MutableStateFlow 制作運算子擴展函式,以將其用作屬性委托。
private val userFlow = MutableStateFlow<User?>(null)
var user: User?
get() = userFlow.value
set(value) {
userFlow.value = value
}
val userPosts: Flow<List<Post>> = userFlow.flatMapLatest { user ->
if (user == null) emptyFlow() else database.getAllPostsForUser(user)
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/345174.html
標籤:科特林 android-room
