← Назад к вопросам

Как сохранить состояние при смене конфигурации

2.0 Middle🔥 211 комментариев
#Android компоненты#Жизненный цикл и навигация

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Сохранение состояния при смене конфигурации в Android

Сохранение состояния при смене конфигурации (например, поворот экрана) — одна из фундаментальных задач в разработке Android-приложений. При смене конфигурации система по умолчанию уничтожает и пересоздает активити, что может привести к потере пользовательских данных, если не предпринять специальных мер. Рассмотрим основные подходы и лучшие практики.

Основные механизмы сохранения состояния

1. onSaveInstanceState() и onRestoreInstanceState()

Базовый механизм для сохранения временных данных. Подходит для небольших объемов данных (примитивные типы, Parcelable объекты).

class MainActivity : AppCompatActivity() {
    private var counter = 0
    
    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        outState.putInt("COUNTER_KEY", counter)
    }
    
    override fun onRestoreInstanceState(savedInstanceState: Bundle) {
        super.onRestoreInstanceState(savedInstanceState)
        counter = savedInstanceState.getInt("COUNTER_KEY", 0)
    }
}

2. ViewModel + SavedStateHandle

Современный рекомендуемый подход, который отделяет логику сохранения состояния от жизненного цикла UI компонентов.

class MainViewModel(
    private val savedStateHandle: SavedStateHandle
) : ViewModel() {
    
    companion object {
        private const val COUNTER_KEY = "counter_key"
    }
    
    val counter: LiveData<Int> = savedStateHandle.getLiveData(COUNTER_KEY, 0)
    
    fun incrementCounter() {
        savedStateHandle[COUNTER_KEY] = (counter.value ?: 0) + 1
    }
}

Продвинутые стратегии

Разделение по типам данных:

  • Постоянные данные — сохраняются в базу данных, SharedPreferences или файлы
  • Временные данные сессии — сохраняются через ViewModel или onSaveInstanceState
  • Восстанавливаемые ресурсы — загружаются заново при создании активити

Использование архитектурных компонентов:

@Composable
fun CounterScreen(
    viewModel: CounterViewModel = viewModel()
) {
    val counter by viewModel.counter.collectAsState()
    
    Column {
        Text(text = "Count: $counter")
        Button(onClick = { viewModel.increment() }) {
            Text("Increment")
        }
    }
}

Рекомендации и лучшие практики

  1. Используйте ViewModel как основной инструмент для хранения UI-состояния — он переживает смену конфигурации.

  2. Различайте конфигурационные изменения и реальное уничтожение процесса:

    • Для сохранения при уничтожении процесса используйте onSaveInstanceState()
    • Для смены конфигурации достаточно ViewModel
  3. Избегайте сохранения тяжелых объектов в Bundle — используйте идентификаторы и перезагружайте данные.

  4. Для сложных UI состояний комбинируйте несколько подходов:

    • ViewModel для бизнес-логики
    • SavedStateHandle для восстановления после смерти процесса
    • Локальная база данных для постоянных данных
  5. Тестируйте сценарии:

    // Включение смены конфигурации в эмуляторе
    adb shell am broadcast -a com.android.intent.action.SET_TEST_CONFIGURATION
    

Распространенные ошибки

  • Слишком много данных в Bundle — приводит к TransactionTooLargeException
  • Игнорирование смерти процесса — только смена конфигурации покрывается ViewModel
  • Смешивание логики восстановления и бизнес-логики — нарушает принцип единственной ответственности

Ключевой принцип: проектируйте архитектуру так, чтобы восстановление состояния было естественной частью жизненного цикла компонентов, а не "костылем". Современные подходы с ViewModel, SavedStateHandle и архитектурой MVVM/MVI позволяют создавать устойчивые к изменениям конфигурации приложения с чистым и поддерживаемым кодом.