Передача данных обратно в предыдущий фрагмент с помощью Android Navigation

Я начал использовать компоненты архитектуры Android (навигация и безопасные аргументы, модели просмотра) вместе с библиотекой Koin.

В настоящее время у меня проблема с передачей аргументов между двумя фрагментами - мне нужно передать строковое значение из фрагмента A во фрагмент B, изменить это значение во фрагменте B и передать его обратно фрагменту A.

Я нашел одно возможное решение своей проблемы - модели общего представления. К сожалению, у этого подхода есть одна проблема, потому что я могу передавать и изменять значения между экранами, но когда фрагмент A переходит в другое место назначения, значение в модели общего представления все еще сохраняется и не очищается.

Есть ли другое решение для передачи и изменения данных между фрагментами в Android Navigation? Я хочу избежать очистки этого значения вручную (когда фрагмент A уничтожен).


comment
ты решил это?   -  person user924    schedule 02.10.2019
comment
ищу решение для подобного сценария. Это решено, пожалуйста, обновите?   -  person Faisal    schedule 30.10.2019
comment
См. stackoverflow.com/questions/50754523/. По сути, поделитесь ViewModel.   -  person Graham Perks    schedule 04.12.2019
comment
Ознакомьтесь с ответом здесь. Они только недавно добавили функциональность в библиотеку навигации.   -  person LeHaine    schedule 31.03.2020


Ответы (4)


Android только что выпустил решение для этого; Передача данных между пунктами назначения (Navigation 2.3.0-alpha02 < / strong>), в основном, во фрагменте A вы наблюдаете изменения в переменной, а во фрагменте B вы изменяете это значение перед выполнением popBackStack().

Фрагмент A:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val navController = findNavController();
// We use a String here, but any type that can be put in a Bundle is supported
navController.currentBackStackEntry?.savedStateHandle?.getLiveData<String>("key")?.observe(
    viewLifecycleOwner) { result ->
    // Do something with the result.
  }
}

Фрагмент Б:

navController.previousBackStackEntry?.savedStateHandle?.set("key", result)
navController.popBackStack()
person zgluis    schedule 15.04.2020
comment
Спасибо! Это работает, но это очень странное решение по сравнению с тем, когда вы передаете данные из фрагмента A во фрагмент B. Это решение больше похоже на старый способ передачи данных с использованием пакета, как мы привыкли делать в Java. - person Shan Xeeshi; 21.06.2021

В настоящее время у меня проблема с передачей аргументов между двумя фрагментами - мне нужно передать строковое значение из фрагмента A во фрагмент B, изменить это значение во фрагменте B и передать его обратно фрагменту A.

Теоретическое решение действительно состоит в том, чтобы иметь два фрагмента в общем теге <navigation, а затем ограничить ViewModel идентификатором тега навигации, таким образом вы теперь разделяете ViewModel между двумя экранами.

Чтобы сделать это надежным, лучше всего использовать NavBackStackEntry тега Navigation как ViewModelStoreOwner и SavedStateRegistryOwner, а также создать AbstractSavedStateViewModelFactory, который создаст ViewModel с помощью ViewModelProvider, а также предоставит вам SavedStateHandle.

Вы можете передать результаты от FragmentB к FragmentA с помощью этого SavedStateHandle, связанного с общей ViewModel (с областью действия совместно используемой NavGraph).

person EpicPandaForce    schedule 10.06.2020

Вы можете попробовать это решение

<fragment
    android:id="@+id/a"
    android:name="...">

    <argument
        android:name="text"
        app:argType="string" />

    <action
        android:id="@+id/navigate_to_b"
        app:destination="@id/b" />

</fragment>

<fragment
    android:id="@+id/b"
    android:name="...">

    <argument
        android:name="text"
        app:argType="string" />

    <action
        android:id="@+id/return_to_a_with_arguments"
        app:destination="@id/a"
        app:launchSingleTop="true"
        app:popUpTo="@id/b"
        app:popUpToInclusive="true" />

</fragment>

и фрагмент навигации

NavHostFragment.findNavController(this).navigate(BFragmentDirections.returnToAWithArguments(text))

комментарий ianhanniballake помог мне решить аналогичную проблему.

person Artem Motuzniy    schedule 10.06.2020

1) Передайте строку из фрагмента A во фрагмент B с помощью action_A_to_B и SafeArgs.

2) popBackStack для удаления фрагмента B.

navController.popBackStack(R.id.AFragment, false);

or

navController.popBackStack();

3) Затем передайте измененные данные от B к A с помощью action_B_to_A.

ИЗМЕНИТЬ.

Здесь у вас есть еще одно решение.

person Klaudia    schedule 23.05.2019