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

Как FragmentManager узнает что надо вызывать метод onSavedStateHandle

2.8 Senior🔥 101 комментариев
#Android компоненты#Жизненный цикл и навигация

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

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

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

Механизм сохранения состояния 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()
    }
}

Ключевые моменты времени вызова:

  1. При изменении конфигурации (поворот экрана)
  2. При переходе Activity в фон с возможностью уничтожения
  3. При вызове finish() у родительского Activity
  4. При вызове 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)
        }
    }
}

Иерархия вызовов:

  1. Activity.onSaveInstanceState()
  2. FragmentController.saveAllState()
  3. FragmentManager.saveAllState()
  4. Fragment.performSaveInstanceState()
  5. 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().