ViewModelとの連携

コードは参考サイトからの流用になります。
ViewModelの定義の中で変更を検知したい値(count)をMutableLiveDataとして定義する。初期値はここでは0

class SampleViewModel: ViewModel() {
    val count = MutableLiveData(0)

    fun countUp() {
        val c = count.value ?: 0
        count.value = c + 1
    }
}

ViewModelのパラメータの変更を監視するには、observeAsState()を使います。このAPIによって、LiveDataをStateとして扱うことができます。つまり、LiveDataの値が変更されたことをコンポーザブルが検出し、UIの再構築が行われます。その結果、LiveDataの値の変更が画面表示に反映されるのです。

@Composable
fun AppScreen(viewModel: SampleViewModel = viewModel()) {
    val count: Int by viewModel.count.observeAsState(0)
    Column {
        Text(text = "Count: $count")
        Button(onClick = {viewModel.countUp()}) {
            Text(text = "Count up")
        }
    }
}

ここでデフォルト引数としてviewModel()としておくことで上位から渡さなくてもすでに対象のViewModelがインスタンス化されている場合は、そのインスタンスを返してくれる。
上記のComposableの表示

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            AppScreen()
        }
    }
}

なので複数のComposableからViewModelを利用する場合も以下のようにできる

@Composable
fun AppScreen() {
    Column {
        CountText()
        CountButton()
    }
}

@Composable
fun CountText(viewModel: SampleViewModel = viewModel()) {
    val count: Int by viewModel.count.observeAsState(0)
    Text(text = "Count: $count")
}

@Composable
fun CountButton(viewModel: SampleViewModel = viewModel()) {
    Button(onClick = {viewModel.countUp()}) {
        Text(text = "Count up")
    }
}

参考
Jetpack Compose入門(16) ViewModelとの連携 - 縁側プログラミング