Комментарии (3)
Ответ сгенерирован нейросетью и может содержать ошибки
Функция rememberSavable в Jetpack Compose
rememberSavable — это расширенная версия функции remember в Jetpack Compose, которая позволяет сохранять состояние композиции не только во время рекомпозиции, но и при изменении конфигурации (например, повороте экрана) и даже между перезапусками процесса, используя механизм SavedInstanceState.
Основное предназначение
В отличие от обычного remember, который хранит состояние только в течение жизни композиции (до ее выхода из Composition), rememberSavable автоматически сохраняет данные в Bundle при уничтожении активити/фрагмента и восстанавливает их при повторном создании. Это критически важно для:
- Сохранения UI-состояния при повороте устройства
- Восстановления данных после убийства процесса системой (process death)
- Работы с конфигурационными изменениями без потери введенных пользователем данных
Ключевые характеристики
@Composable
fun <T : Any> rememberSavable(
vararg inputs: Any?,
saver: Saver<T, out Any> = autoSaver(),
key: String? = null,
init: () -> T
): T
Параметры:
inputs— зависимости, при изменении которых значение будет пересчитываться (аналогичноremember)saver— определяет способ сериализации/десериализации значенияkey— дополнительный ключ для идентификации в Bundleinit— инициализатор, создающий начальное значение
Работа с Saver-ами
Saver — это интерфейс, определяющий как объект преобразуется в сохраняемое состояние и обратно:
interface Saver<T : Any, Saveable : Any> {
fun SaverScope.save(value: T): Saveable?
fun restore(value: Saveable): T?
}
Jetpack Compose предоставляет несколько встроенных Saver-ов:
autoSaver()— автоматически работает с типами, поддерживающими@ParcelizelistSaver(),mapSaver()— для коллекций- Создание кастомных Saver-ов для сложных объектов
Примеры использования
Базовый пример с примитивными типами:
@Composable
fun CounterScreen() {
// Состояние сохранится при повороте экрана
var count by rememberSavable { mutableStateOf(0) }
Column {
Text("Count: $count")
Button(onClick = { count++ }) {
Text("Increment")
}
}
}
Работа с кастомными объектами:
@Parcelize
data class UserSettings(
val theme: String,
val notificationsEnabled: Boolean
) : Parcelable
@Composable
fun SettingsScreen() {
// autoSaver автоматически использует Parcelable
var settings by rememberSavable { mutableStateOf(UserSettings("Light", true)) }
// ... UI для изменения настроек
}
Кастомный Saver для сложных объектов:
data class ComplexData(val id: Int, val name: String)
val complexDataSaver = run {
mapSaver<ComplexData>(
save = { mapOf("id" to it.id, "name" to it.name) },
restore = { ComplexData(it["id"] as Int, it["name"] as String) }
)
}
@Composable
fun ComplexScreen() {
var data by rememberSavable(
saver = complexDataSaver
) { mutableStateOf(ComplexData(1, "Test")) }
}
Внутренняя механика работы
- Сохранение: При уничтожении активити, Compose runtime собирает все значения, созданные через
rememberSavable, и сохраняет их вBundleчерез соответствующие Saver-ы - Восстановление: При создании новой инстанции активити, Compose восстанавливает значения из
Bundleи передает их в композицию - Интеграция с
remember:rememberSavableвнутренне использует обычныйremember, добавляя к нему логику сохранения/восстановления
Важные ограничения и лучшие практики
Ограничения:
- Размер данных: Bundle имеет ограничения по размеру (обычно 500KB-1MB)
- Производительность: Частое сохранение больших объектов может влиять на производительность
- Типы данных: Не все типы можно сохранить по умолчанию
Рекомендации:
- Используйте
rememberдля временных UI-состояний (анимации, флаги) - Используйте
rememberSavableдля данных, которые должны пережить изменение конфигурации - Для больших или сложных данных используйте ViewModel + сохранение в базу данных/Preferences
- Для объектов, не поддерживающих Parcelable, создавайте кастомные Saver-ы
Отличия от альтернативных подходов
| Подход | Сохраняет при повороте | Сохраняет при убийстве процесса | Сложность |
|---|---|---|---|
remember | ❌ | ❌ | Низкая |
rememberSavable | ✅ | ✅ | Средняя |
ViewModel | ✅ | ❌ (только с SavedStateHandle) | Высокая |
LocalSaveStateRegistry | ✅ | ✅ | Очень высокая |
Типичные сценарии использования
- Формы ввода данных — сохранять частично заполненные поля
- Состояние UI-компонентов — открытые/закрытые состояния раскрывающихся списков
- Текущий прогресс — в многошаговых процессах или wizard-ах
- Временные фильтры и сортировки — в списках данных
Функция rememberSavable заполняет важную нишу между простым remember и полноценными архитектурными компонентами, предоставляя удобный способ сохранения состояния без излишней сложности. Однако для управления бизнес-логикой и большими объемами данных рекомендуется использовать ViewModel в сочетании с SavedStateHandle, который internally также использует похожие механизмы сохранения состояния.