Компонент LiveData представляет еще один способ управления дангными в ViewModel и может использоваться в качестве обертки для данных во ViewModel. После помещения в LiveData данные становятся доступными для компонентов внутри класса Activity. Объекты LiveData можно объявить как изменяемые с помощью класса MutableLiveData, что позволяет функциям ViewModel вносить изменения в базовые значения данных.
Для работы с LiveData в файле
libs.versions.toml в секции [libraries]
укажем саму библиотеку, а в секции [versions]
укажем версию этой библиотеки:
[versions] runtimeLivedata = "1.6.5" ....................... [libraries] androidx-runtime-livedata = { module = "androidx.compose.runtime:runtime-livedata", version.ref = "runtimeLivedata" } androidx-lifecycle-viewmodel-compose = { module = "androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "lifecycleRuntimeKtx" } ....................
Далее в секции [versions]
укажем версию этой библиотеки:
[versions] .................. roomRuntime = "2.6.1"
Затем в файл build.grade.kts добавим соответствующую зависимость:
То есть в итоге получится
dependencies { implementation (libs.androidx.runtime.livedata) implementation(libs.androidx.lifecycle.viewmodel.compose) implementation(libs.androidx.core.ktx) // остальные зависимости ........................................ }
Пример ViewModel, которая использует LiveData:
class LiveCounterViewModel : ViewModel() { var count: MutableLiveData<Int> = MutableLiveData(0) fun increase() { count.value = count.value!! + 1 } }
Здесь у нас есть переменная count, которая представляет тип MutableLiveData<Int>
- обертку над числом. И есть функция increase, которая увеличивает значение в count. Поскольку теоретически
значение в MutableLiveData может представлять null, однако в нашем случае это невозможная ситуация, так как значение в любом случае представляет некоторое число, то при увеличении с помощью оператора !!
говорим, что это значение не равно null.
Так, перепишем прошлый пример, использовав LiveData:
package com.example.helloapp import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.material3.Button import androidx.compose.material3.Text import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.unit.sp import androidx.lifecycle.ViewModel import androidx.compose.runtime.Composable import androidx.compose.runtime.livedata.observeAsState import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewmodel.compose.viewModel class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { CounterView() } } } class LiveCounterViewModel : ViewModel() { var count: MutableLiveData<Int> = MutableLiveData(0) fun increase() { count.value = count.value!! + 1 } } @Composable fun CounterView(vm: LiveCounterViewModel = viewModel()) { val countValue by vm.count.observeAsState(0) Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) { Text("Count: ${countValue}", Modifier.padding(10.dp), fontSize = 25.sp) Button(onClick = {vm.increase()}) { Text(text = "Increase", fontSize = 25.sp) } } }
Здесь определен компонент верхнего уровня CounterView, который инкапсулирует весь остальной интерфейс. В этот компонент в качестве параметра передается объект LiveCounterViewModel - наш ViewModel, который определяет состояние - переменную count и функцию increase для изменения этого состояния. Причем для создания CounterViewModel применяется не его конструктор, а функция viewModel(). Если экземпляр ViewModel (в нашем случае LiveCounterViewModel) уже создан в текущем контексте, то функция viewModel() вернет ссылку на этот экземпляр. В противном случае будет создан и возвращен новый экземпляр ViewModel.
Для отслеживания изменения значения в LiveData компонент определяет дополнительную переменную countValue:
val countValue by vm.count.observeAsState(0)
Вызов функции observeAsState()
преобразует значение из LiveData в объект состояния и присваивает его переменной countValue. После преобразования это состояние будет отслеживать,
и при его изменении будет запускаться рекомпозиция при компонента.
Внутри CounterView определяем текстовую метку, которая выводит состояние, и кнопку, которая вызывает функцию increase. Таким образом, при нажатии на кнопку произойдет вызов функции increase, которая, в свою очередь, увеличивает состояние count. Это изменение состояния вызывает рекомпозицию пользовательского интерфейса, в результате чего новое значение count отобразится в компоненте Text: