当我在 Kotlin 中使用 Compose 时,从 Flow 进行收集的操作会消耗大量系统资源吗?

Hel*_*oCW 4 kotlin kotlin-coroutines android-jetpack-compose kotlin-flow

SoundViewModel是一个ViewModel类,val listSoundRecordState可能被应用程序中的某些模块使用。

在代码 A 中,我fun collectListSoundRecord()在需要使用数据时调用listSoundRecordState。但fun collectListSoundRecord()可能会因为Jetpack Compose重新组合而反复启动,不知道会不会耗费很多系统资源?

在代码B中,我 private fun collectListSoundRecord()在 中启动init { }collectListSoundRecord()只会启动一次,但即使我不需要使用数据listSoundRecordState,它也会保留在内存中直到App代码关闭,这种方式会消耗很多系统资源吗?

代码A

@HiltViewModel
class SoundViewModel @Inject constructor(
  ...
): ViewModel() {

    private val _listSoundRecordState = MutableStateFlow<Result<List<MRecord>>>(Result.Loading)
    val listSoundRecordState = _listSoundRecordState.asStateFlow()

    init { }

     //It may be launched again and again
    fun collectListSoundRecord(){
        viewModelScope.launch {
            listRecord().collect {
                result -> _listSoundRecordState.value =result
            }
        }
    }

    private fun listRecord(): Flow<Result<List<MRecord>>> {
        return  aSoundMeter.listRecord()
    }

}
Run Code Online (Sandbox Code Playgroud)

代码B

@HiltViewModel
class SoundViewModel @Inject constructor(
  ...
): ViewModel() {

    private val _listSoundRecordState = MutableStateFlow<Result<List<MRecord>>>(Result.Loading)
    val listSoundRecordState = _listSoundRecordState.asStateFlow()

    init { collectListSoundRecord() }

    private fun collectListSoundRecord(){
        viewModelScope.launch {
            listRecord().collect {
                result -> _listSoundRecordState.value =result
            }
        }
    }

    private fun listRecord(): Flow<Result<List<MRecord>>> {
        return  aSoundMeter.listRecord()
    }

}
Run Code Online (Sandbox Code Playgroud)

Hor*_*rea 5

listRecord()仅当中间流有订阅者(您保留在 中SoundViewModel)并缓存结果时,您可能会受益于收集原始流(来自)。

在您的情况下,订阅者将是一个Composable收集值的函数(并且可能经常重新组合)。

您可以使用 的非暂停变体来实现此目的stateIn(),因为您有一个默认值。

@HiltViewModel
class SoundViewModel @Inject constructor(
    ...
): ViewModel() {

    val listSoundRecordState = listRecord().stateIn(viewModelScope, SharingStarted.WhileSubscribed(), Result.Loading)

    private fun listRecord(): Flow<Result<List<MRecord>>> {
        return  aSoundMeter.listRecord()
    }
}
Run Code Online (Sandbox Code Playgroud)

为了使用StateFlowUI 层(@Composable函数)中的 ,您必须将其转换为State,如下所示:

val viewModel: SoundViewModel = viewModel()
val listSoundRecord = viewModel.listSoundRecordState.collectAsState()
Run Code Online (Sandbox Code Playgroud)