Soh*_*ikh 1 android mvvm coroutine kotlin-flow
我在存储库中有一个函数,它根据参数从网络或远程数据源返回响应。
图书库:
suspend fun getBooks(isNetwork: Boolean) : Flow<Books>
Run Code Online (Sandbox Code Playgroud)
我想在视图模型中收集它,但每次调用 ViewModel 方法时都会创建一个新的协程。我知道我应该在暴露给 UI 层之前映射流程,但是如何将参数传递给函数呢?
图书视图模型:
fun getBooks(isNetwork: Boolean) {
viewModelScope.launch {
bookRepository.getBooks(isNetwork).collectLatest { books ->
...
}
}
}
Run Code Online (Sandbox Code Playgroud)
这里getBooks函数也用于进行网络调用,需要多次调用。每次调用 ViewModel 中的 getBooks 时,都会创建一个新的协程,从而创建多个观察者。
您根本不应该使用viewModelScope.launch此功能 - 即使您的 UI 消失(即,当您的屏幕进入后退堆栈或用户点击主页按钮时),它也会继续运行。
相反,您需要:
isNetwork在 ViewModel 中。公开 setter,以便您的 UI 可以在用户请求网络数据时更新状态。isNetwork状态作为调用的输入bookRepository.getBooksshareIn以确保您始终返回单个 Flow 对象,该对象根据Android SharedFlow 指南在配置更改时保留缓存数据。这意味着你的ViewModel看起来更像是:
class YourViewModel(
// Let's assume you are using some sort of dependency injection
bookRepository: BookRepository
) : ViewModel() {
// Keep your internal state as an observable MutableStateFlow
// here defaulting to isNetwork = false
private val isNetworkFlow = MutableStateFlow(false)
// Allow your UI to change whether isNetwork is true or false
public fun useNetwork(isNetwork) {
isNetworkFlow.value = isNetwork
}
// Transform each output of isNetworkFlow into a
// new Flow from the bookRepository
public val booksFlow: Flow<List<Books>> = isNetworkFlow.flatMapLatest { isNetwork ->
bookRepository.getBooks(isNetwork)
}.shareIn( // Only collect from the booksRepository when the UI is visible
viewModelScope,
started = SharingStarted.WhileSubscribed(5000),
replay = 1
)
}
Run Code Online (Sandbox Code Playgroud)
现在,只要用户愿意,您的 UI 就可以collect打开并调用以交换到网络源。booksFlowonViewCreateduseNetwork(true)
如果您有更复杂的情况(例如,布尔值可能不够),那么同样的方法也可以用于其他状态。
| 归档时间: |
|
| 查看次数: |
2578 次 |
| 最近记录: |