Jetpack compose MutableStateFlow Counter application

MutaleState

A mutable value holder where reads to the value property during the execution of a Composable function, the current RecomposeScope will be subscribed to changes of that value. When the value property is written to and changed, a recomposition of any subscribed RecomposeScopes will be scheduled. If the value is written to with the same value, no recompositions will be scheduled.

A subtype of State that allows setting value. When the value is changed, any snapshot observers that read value will be notified when the snapshot is applied. (i.e. when preparing the next frame). It’s a common pattern to hold a MutableState as a private class property, then expose it publicly either as a State or as a regular property that has the type T. State is to MutableState as List is to MutableList.

Refresh data: vm.countState.collectAsState().value

viewmodel

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch

class ShoppingRepository : ViewModel() {

    private var _countState: MutableStateFlow<Int> = MutableStateFlow(0)

    val countState = _countState.asStateFlow()
    //val countState: StateFlow<Int> get() = _countState

    fun incrementCount() {
        println(countState.value)
        viewModelScope.launch {
            _countState.value += 1
        }
    }

    fun decrementCount() {
        viewModelScope.launch {
            _countState.value -= 1
        }
    }
}

UI

import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.Alignment
import androidx.compose.ui.text.style.TextAlign
import androidx.lifecycle.viewmodel.compose.viewModel
import com.sunsine.jetpack.repository.ShoppingRepository

@Composable
fun ShoppingView() {
    
    Surface(
        modifier = Modifier
            .fillMaxSize()
            .padding(16.dp)
    ) {
        Row() {
            shoppingVM()
        }
    }
}

@Composable
fun shoppingVM() {
    val vm: ShoppingRepository = viewModel()
    ShoppingCart("${vm.countState.collectAsState().value}", addOnClick = { vm.incrementCount() }, minusOnClick = { vm.decrementCount() })
}

@Composable
fun ShoppingCart(text: String, addOnClick: () -> Unit = {}, minusOnClick: () -> Unit = {}) {
    Row (verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.Center,
        modifier = Modifier
            .fillMaxHeight()
            .fillMaxWidth()

    ){
        Button(
            onClick = minusOnClick,
        ) {
            Text(text = " - ")
        }
        Text(text, textAlign = TextAlign.Center)
        Button(
            onClick = addOnClick,
        ) {
            Text(text = " + ")
        }
    }
}