Как FragmentManager узнает что надо вызывать метод onSavedStateHandle
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Механизм сохранения состояния Fragment через onSaveInstanceState
FragmentManager не вызывает onSaveInstanceState() напрямую у фрагментов. Вместо этого работает цепочка взаимодействий между Activity, FragmentManager и FragmentController. Вот подробный механизм:
1. Инициирование процесса сохранения
Когда система Android уничтожает Activity (например, при повороте экрана или нехватке памяти), она вызывает:
// В Activity происходит вызов:
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
// Activity делегирует сохранение состояния фрагментов
}
2. Делегирование FragmentController
Activity делегирует сохранение состояния фрагментов FragmentController, который является прослойкой между Activity и FragmentManager:
// В FragmentController:
public void saveAllState() {
// Создает Bundle для сохранения состояния всех фрагментов
FragmentManagerState fragmentManagerState = mFragmentManager.saveAllState();
// Сохраняет:
// 1. Список активных фрагментов
// 2. Стек back stack
// 3. Состояние каждого фрагмента
}
3. Роль FragmentManager
FragmentManager проходит по всем активным фрагментам и собирает их состояние:
// Псевдокод логики FragmentManager:
fun saveAllState(): FragmentManagerState {
val result = FragmentManagerState()
// Сохраняем информацию о фрагментах
for (fragment in mActive.values) {
if (fragment != null) {
// Ключевой момент: сохранение состояния фрагмента
val fragmentState = FragmentState(fragment)
// Здесь вызывается onSaveInstanceState()
if (fragment.mState >= Fragment.CREATED) {
fragment.performSaveInstanceState(savedInstanceState)
}
}
}
return result
}
4. Вызов onSaveInstanceState() у Fragment
Внутри performSaveInstanceState() происходит фактический вызов:
// В классе Fragment:
void performSaveInstanceState(Bundle outState) {
onSaveInstanceState(outState); // 1. Вызывается метод фрагмента
// 2. Сохраняется состояние View, если они есть
if (mView != null) {
saveHierarchyState(outState);
}
// 3. Сохраняется состояние дочерних FragmentManager
if (mChildFragmentManager != null) {
mChildFragmentManager.saveAllState()
}
}
Ключевые моменты времени вызова:
- При изменении конфигурации (поворот экрана)
- При переходе Activity в фон с возможностью уничтожения
- При вызове finish() у родительского Activity
- При вызове commit() с addToBackStack() (для восстановления)
Особенности работы:
class ExampleFragment : Fragment() {
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
// Сохраняем данные
outState.putString("KEY_DATA", importantData)
outState.putInt("KEY_COUNTER", counterValue)
// Важно: View уже автоматически сохраняют свое состояние
// через saveHierarchyState(), если у них есть ID
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// Восстановление данных
savedInstanceState?.let {
importantData = it.getString("KEY_DATA")
counterValue = it.getInt("KEY_COUNTER", 0)
}
}
}
Иерархия вызовов:
- Activity.onSaveInstanceState() →
- FragmentController.saveAllState() →
- FragmentManager.saveAllState() →
- Fragment.performSaveInstanceState() →
- Fragment.onSaveInstanceState()
Важные нюансы:
- View состояния сохраняются автоматически, если у View есть ID
- Жизненный цикл:
onSaveInstanceState()вызывается ДОonStop(), но ПОСЛЕonPause() - Не вызывается при явном finish() без возможности восстановления
- ViewModel с SavedStateHandle предоставляет более современный способ сохранения состояния
Пример с SavedStateHandle:
class MyViewModel(
private val savedStateHandle: SavedStateHandle
) : ViewModel() {
// Автоматически сохраняется и восстанавливается
val liveData: LiveData<String> = savedStateHandle.getLiveData("key", "")
fun saveData(value: String) {
savedStateHandle["key"] = value
}
}
// В Fragment:
class MyFragment : Fragment() {
private val viewModel: MyViewModel by viewModels()
// Не нужно переопределять onSaveInstanceState()
// Все данные хранятся в ViewModel
}
Ключевое отличие: SavedStateHandle работает через SavedStateRegistry, который интегрируется с системой сохранения состояния, но предоставляет более декларативный и типобезопасный API по сравнению с ручным управлением Bundle в onSaveInstanceState().