Навигация по сохранению состояния композиции прервалась после обновления до новой версии библиотеки

#android #android-jetpack-compose #jetpack-compose-navigation

Вопрос:

Однажды мне понадобилась библиотека аккомпаниаторов Google, реализованная в моем проекте создания Jetpack. Поскольку библиотека зависит от текущей стабильной версии Compose, мне пришлось обновить ее вместе с navigation-compose библиотекой. Все сломалось.

Я использую BottomNavigation в качестве навигации верхнего уровня и глубже ориентируюсь внутри вкладок, связанных с этим BottomNavigation . Каждая вкладка имеет свою собственную NavHostController , которую я хочу сохранить в a Bundle , чтобы восстановить контроллер позже. Пример использования:

  1. Пользователь открывает вкладку 1
  2. Переход на другой экран с внутренней вкладки 1
  3. Переключается на вкладку 2
  4. Переключается обратно на вкладку 1. Экран, открытый на шаге 2, является текущим местом назначения вкладки 1 NavGraph

Код, приведенный в Предыдущем состоянии, работает по назначению.

До

Мои зависимости до миграции(составьте версию 1.0.0-alpha12):

     // Compose
    implementation "androidx.compose.ui:ui:$compose_version"
    implementation "androidx.compose.material:material:$compose_version"
    implementation "androidx.compose.ui:ui-tooling:$compose_version"
    implementation "androidx.compose.material:material-icons-extended:$compose_version"
    implementation "androidx.compose.runtime:runtime-livedata:$compose_version"
    implementation "androidx.navigation:navigation-compose:1.0.0-alpha07"
 

В моем составном устройстве верхнего уровня, где BottomNavigation это называется, у меня есть состояние:

     val employeesNavState = rememberSaveable { mutableStateOf(Bundle()) }
 

Который я передаю на свою вкладку composable:

 EmployeesTab(employeesNavState)
 

Это описывается следующей функцией:

 @Composable
fun EmployeesTab(navState: MutableState<Bundle>) {
    val navController = rememberNavController() // The navController responsible for navigation state
    DisposableEffect(null) {
        val callback = NavController.OnDestinationChangedListener { controller, _, _ ->
            // The state is saved on each navigation event
            navState.value = controller.saveState() ?: Bundle()
        }
        navController.addOnDestinationChangedListener(callback)
        // The state is restored from the navState created by the callback
        navController.restoreState(navState.value)

        onDispose {
            navController.removeOnDestinationChangedListener(callback)
            // workaround for issue where back press is intercepted
            // outside this tab, even after this Composable is disposed
            navController.enableOnBackPressed(false)
        }
    }

    NavHost(navController, startDestination = "employees") {
        composable("employees") {
            appBarViewModel.onNavigate(AppScreen.Employees, navController)
            Employees(it.hiltViewModel(), navController)
        }
        composable("employee/{userId}") {
            appBarViewModel.onNavigate(AppScreen.EmployeeDetails, navController)
            Employee(it.hiltViewModel())
        }
    }
}
 

После

Мои зависимости после миграции(составьте версию 1.0.3):

     // Compose
    implementation "androidx.compose.ui:ui:$compose_version"
    implementation "androidx.compose.material:material:$compose_version"
    implementation "androidx.compose.ui:ui-tooling:$compose_version"
    implementation "androidx.compose.material:material-icons-extended:$compose_version"
    implementation "androidx.compose.runtime:runtime-livedata:$compose_version"
    implementation "androidx.navigation:navigation-compose:2.4.0-alpha10"
    implementation "com.google.accompanist:accompanist-flowlayout:0.19.0"
 

И каждый отдельный бит другого кода остается прежним. Каким-то образом это просто перестало работать. Я сделал некоторую отладку и убедился controller.saveState() , что не возвращается null . Обратный вызов выполняется в обеих версиях.

Единственное , что я обнаружил, что отличается, — это navigate() функция NavController , которая является функцией расширения navigation-compose:1.0.0-alpha07 и функцией-членом navigation-compose:2.4.0-alpha10 . Я называю это изнутри Employees составного.

Вопрос

Что изменилось внутри API, что он перестал работать без каких-либо ошибок? Как мне изменить свой код, чтобы воспроизвести поведение «До»?

Комментарии:

1. Почему вы вообще используете несколько навигационных хостов? Вам не нужно ничего из этого, чтобы сохранить состояние каждой вкладки — это то saveState restoreState , что делают для вас флаги и в примере интеграции нижней навигации .

2. @ianhanniballake, я унаследовал этот проект от другого разработчика, и вот как он реализовал это поведение. Я последую примеру по предоставленной ссылке и опубликую обновление. Спасибо