Android中如何收集多个状态流

问题描述 投票:0回答:3

如何采集activity中的两个状态流?因为我只消耗了第一个流量。

例如,viewmodel内部是这样的:

class ExampleViewModel: ViewModel(){
    private val state = MutableStateFlow<HomeMainFragmentState>(HomeMainFragmentState.Init)
    private val products = MutableStateFlow<List<ProductEntity>>(mutableListOf())


    //to be consumed
    fun getState() : StateFlow<HomeMainFragmentState> = state
    fun getProducts() : StateFlow<List<ProductEntity>> = products
}

然后在我看来是这样的:

private fun observe(){
      viewLifecycleOwner.lifecycleScope.launch {
      viewLifecycleOwner.lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED){
            viewModel.getState().collect { state -> handleState(state) }
            viewModel.getProducts().collect{ products -> handleProducts(products) }
        }
    }
}

问题是,仅消耗第一个流,因为这种情况是“状态”产品从未被活动/片段消耗/执行。

如何解决这个问题? 我还阅读了有关组合流程的内容,这是否意味着第二个流程取决于第一个流程的运行?

android kotlin android-livedata kotlin-flow
3个回答
21
投票

您必须为每个收集器使用

CoroutineScope.launch
功能。

viewLifecycleOwner.lifecycleScope.launch {
    viewLifecycleOwner.lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED){
        launch {
            viewModel.getState().collect { state -> handleState(state) }
        }
        launch {
            viewModel.getProducts().collect{ products -> handleProducts(products) }
        }
    }
}

12
投票

在 Flow 上调用

collect
会暂停协程,直到 Flow 完成。对于 MutableStateFlow,只有在取消时才会完成。因此,通常,当您在 Flow 上调用
collect
时,您不会在该调用下方的协程中执行任何其他操作。

如果您想单独收集每个流,则需要两个协程。

flowOnLifecycle
函数将为您提供更清晰的代码,因此拥有两个协程并不那么痛苦:

private fun observe(){
    viewModel.getState()
        .flowOnLifecycle(Lifecycle.State.STARTED)
        .onEach { state -> handleState(state) }
        .launchIn(lifecycleScope)
    viewModel.getProducts()
        .flowOnLifecycle(Lifecycle.State.STARTED)
        .onEach { products -> handleProducts(products) }
        .launchIn(lifecycleScope)
}

我还想提一下,像

getState
这样的函数名称在 Kotlin 中是不自然的,除非它们是重函数(即使它是必须计算某些内容的重函数,我更喜欢
generateState
calculateState
) 。使用属性更合适:

private val mutableState = MutableStateFlow<HomeMainFragmentState>(HomeMainFragmentState.Init)
val state: StateFlow<HomeMainFragmentState> get() = mutableState

他们表示,在 Kotlin 的“未来”版本中,可能会有更好的语法来公开不需要第二个属性的可变类的只读版本。像这样的东西: private val state = MutableStateFlow<HomeMainFragmentState>(HomeMainFragmentState.Init) public get(): StateFlow<HomeMainFragmentState>



0
投票
androidx.lifecycle.flowWithLifecycle

的片段或活动中使用它。请参阅下面修改后的代码。


viewModel.getState().flowWithLifecycle(lifecycle).onEach { state ->
                state -> handleState(state)
        }.launchIn(lifecycleScope)

        viewModel.getProducts().flowWithLifecycle(lifecycle).onEach { products->
            products -> handleProducts(products) 
        }.launchIn(lifecycleScope)

© www.soinside.com 2019 - 2024. All rights reserved.