Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Will the operation of collect from Flow cost many system resources when I use Compose with Kotlin?

The SoundViewModel is a ViewModel class, and val listSoundRecordState may be used by some modules in the App.

In Code A, I invoke fun collectListSoundRecord() when I need to use the data listSoundRecordState. But fun collectListSoundRecord() may be launched again and again because of Jetpack Compose recomposition, I don't know if it will cost many system resources?

In Code B, I launch private fun collectListSoundRecord() in init { }, collectListSoundRecord() will be launched only one time, but it will persist in memory until the App code closed even if I needn't to use the data listSoundRecordState, will the way cost many system resources?

Code 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()
    }

}

Code 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()
    }

}
like image 653
HelloCW Avatar asked Oct 24 '25 14:10

HelloCW


1 Answers

You would probably benefit from collecting the original flow (from listRecord()) only when there is a subscriber to your intermediate flow (the one you keep in your SoundViewModel) and cache the results.

A subscriber, in your case, would be a Composable function that collects the values (and may recompose often).

You can achieve this using the non-suspending variant of stateIn(), since you have a default value.

@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()
    }
}

In order to use the StateFlow from the UI layer (a @Composable function), you will have to transform it into a State, like so:

val viewModel: SoundViewModel = viewModel()
val listSoundRecord = viewModel.listSoundRecordState.collectAsState()
like image 129
Horațiu Udrea Avatar answered Oct 28 '25 05:10

Horațiu Udrea



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!