Я отвечу на ваши вопросы один за другим.
Но это не работает, все текстовые поля сбрасываются при переходе назад к A. Что я делаю не так?
Из FragmentB, когда пользователи заканчивают sh свою работу, и приложение вызывает указанный ниже метод для возврата FragmentA.
findNavController().navigate(R.id.action_from_B_to_A, dataBundle)
Вы ожидали, что приложение вернет пользователей во FragmentA, но фактический результат новый FragmentA создан и помещен в вершину заднего стека. Теперь задний стек будет выглядеть следующим образом.
FragmentA (new instance)
FragmentB
FragmentA (old instance)
Вот почему вы видите, что все текстовые поля сброшены, потому что это совершенно новый экземпляр FragmentA.
Какой правильный способ обрабатывать подобные случаи?
Вы хотите запустить фрагмент, а затем получить результат из этого фрагмента, похоже, startActivityForResult
метод Activity.
In Android Dev Summit 2019 - Компоненты архитектуры , в 2: 43 , есть вопрос для Android разработчиков.
Можем ли мы иметь что-то вроде startFragmentForResult
для Навигационный контроллер?
Ответ - они работают над этим, и эта функция будет доступна в будущем.
Возвращаясь к вашей проблеме, вот мое решение.
Шаг 1: Создайте класс с именем SharedViewModel
class SharedViewModel : ViewModel() {
// This is the data bundle from fragment B to A
val bundleFromFragmentBToFragmentA = MutableLiveData<Bundle>()
}
Шаг 2: Добавьте эти строки кода во FragmentA
private lateinit var viewModel: SharedViewModel
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel = ViewModelProviders.of(requireActivity()).get(SharedViewModel::class.java)
viewModel.bundleFromFragmentBToFragmentA.observe(viewLifecycleOwner, Observer {
// This will execute when fragment B set data for `bundleFromFragmentBToFragmentA`
// TODO: Write your logic here to handle data sent from FragmentB
val message = it.getString("ARGUMENT_MESSAGE", "")
Toast.makeText(requireActivity(), message, Toast.LENGTH_SHORT).show()
})
}
Шаг 3: Добавьте эти строки кода во FragmentB
// 1. Declare this as class's variable
private lateinit var viewModel: SharedViewModel
// 2. Use the following code when you want to return FragmentA
// findNavController().navigate(R.id.action_from_B_to_A) // Do not use this one
// Set data for `bundleFromFragmentBToFragmentA`
val data = Bundle().apply { putString("ARGUMENT_MESSAGE", "Hello from FragmentB") }
viewModel.bundleFromFragmentBToFragmentA.value = data
// Pop itself from back stack to return FragmentA
requireActivity().onBackPressed()