Как сделать изменяемый стейт в Composable функции
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Управление изменяемым состоянием в Jetpack Compose
В Jetpack Comppose для создания изменяемого состояния внутри Composable-функций используются специальные API, которые обеспечивают реактивное обновление UI при изменении данных. Вот основные подходы:
1. mutableStateOf() - базовый строительный блок
Функция mutableStateOf() создает объект MutableState, который уведомляет Compose о необходимости рекомпозиции при изменении значения.
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
@Composable
fun CounterExample() {
// Сохраняем состояние между рекомпозициями
val count = remember { mutableStateOf(0) }
Button(onClick = { count.value++ }) {
Text(text = "Кликов: ${count.value}")
}
}
2. Различные формы объявления состояния
Compose предлагает несколько способов работы с состоянием:
// Способ 1: Явное объявление MutableState
val countState = remember { mutableStateOf(0) }
val count = countState.value
// Способ 2: Деструктуризация (рекомендуется)
var count by remember { mutableStateOf(0) }
// Способ 3: Функция-обертка
val (count, setCount) = remember { mutableStateOf(0) }
3. remember - ключ к сохранению состояния
Функция remember сохраняет значение при рекомпозиции, но сбрасывает при удалении композиции из дерева:
@Composable
fun RememberExample(key: String) {
// Состояние будет сохранено только для конкретного key
var text by remember(key) { mutableStateOf("") }
TextField(
value = text,
onValueChange = { text = it }
)
}
4. ViewModel + mutableState для сложной логики
Для бизнес-логики и сохранения состояния при конфигурационных изменениях используйте ViewModel:
class UserViewModel : ViewModel() {
// StateFlow или LiveData также подойдут
var userName by mutableStateOf("")
private set
fun updateName(newName: String) {
userName = newName
}
}
@Composable
fun UserProfile(viewModel: UserViewModel = viewModel()) {
// Состояние автоматически наблюдается из ViewModel
val userName = viewModel.userName
TextField(
value = userName,
onValueChange = viewModel::updateName
)
}
5. Производные состояния с derivedStateOf
Когда состояние зависит от других состояний, используйте derivedStateOf:
@Composable
fun DerivedStateExample() {
var firstName by remember { mutableStateOf("") }
var lastName by remember { mutableStateOf("") }
val fullName = remember { derivedStateOf { "$firstName $lastName" } }
Text(text = "Полное имя: ${fullName.value}")
}
6. Состояние в списках и коллекциях
Для изменяемых списков используйте специальные mutableState коллекции:
@Composable
fun TodoList() {
// Автоматические уведомления об изменениях в списке
val items = remember { mutableStateListOf<String>() }
LazyColumn {
items(items) { item ->
Text(text = item)
}
}
Button(onClick = { items.add("Новая задача") }) {
Text("Добавить")
}
}
Ключевые принципы:
- Локализуйте состояние - храните состояние в ближайшем общем предке композиций, которые его используют
- Поднимайте состояние вверх (State Hoisting) - когда несколько композиций используют одни данные
- Используйте неизменяемые данные - создавайте новые объекты вместо модификации существующих
- rememberSaveable для сохранения состояния при повороте экрана:
@Composable
fun StateSurvivalExample() {
// Сохраняется в Bundle при изменении конфигурации
var text by rememberSaveable { mutableStateOf("") }
}
Важное замечание: Никогда не изменяйте состояние напрямую внутри Compose-функции без использования реактивных API (mutableStateOf, StateFlow, etc.), так как это не вызовет рекомпозицию и UI не обновится.