In my application I use the Navigation Architecture Component and MVVM architecture (as I understand it, some errors are possible).

I have a main Activity, and the application screens are fragments. we are interested in two of them (let it be Fragment1 and Fragment2).
Part of Fragment1:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) sendCodeButton.setOnClickListener { viewModel.requestResetCode() } viewModel.codeRequestSuccess.observe(this, object : Observer<Boolean> { override fun onChanged(t: Boolean?) { if (t != null && t == true) { view?.findNavController()?.navigate(R.id.action_forgotPasswordFragment_to_resetCodeFragment) } } }) } 

That is, on the first fragment (Fragment1), I move to the second fragment (Fragment2), but this happens not immediately upon pressing, but as soon as the viewModel checks the correctness of the data. For this, Fragment1 keeps track of the codeRequestSuccess variable, which is MutableLiveData .

Here is the code in the ViewModel that is responsible for checking the data:

 fun requestResetCode() { subscription = loginApi.requestResetCode(login.value!!) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .doOnSubscribe { onCodeRequestStart() } .doOnTerminate { onCodeRequestFinish() } .subscribe( { result -> onResetCodeReceived(result) }, { onCodeRequestError() } ) } private fun onResetCodeReceived(result: Boolean) { codeRequestSuccess.value = result } 

The transition is carried out normally, to the desired fragment. But when I later in Fragment2 try to go back to Fragment1:

 override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) backArrow.setOnClickListener { view.findNavController().popBackStack() } } 

Nothing happens, pressing works, but there is no transition. I checked the number of fragments in the stack - 0. At the same time, if in Fragment1 to make a simple transition (for verification) to Fragment2:

 sendCodeButton.setOnClickListener { view.findNavController().navigate(R.id.action_forgotPasswordFragment_to_resetCodeFragment) } 

I understand that the most likely thing is how or where the transition is made. Maybe the wrong thread or process is used, maybe something else related to it. But what exactly is wrong, I can not understand.

  • I advise you to transfer all the logic of working with fragments to Activity. After that, create for each fragment its own interface for interacting with the Activity. (and add it to the Activity), redefine the onBackPressed () method under the desired behavior or add fragments to the FragmentManager with addToBackStack (@param name - or null.) - Serj
  • Thanks for the answer. I tried to make all the navigation in the activation, it did not help. - N.Baklanov

1 answer 1

After much experimentation, I found a solution, but so far I still have not understood until the end of the cause of the error. Most likely, it is related to how Kotlin works with static classes, objects and fields (in my pure form, I don’t have them). Anyway, I simply replaced the change handler declaration with the variable MutableLiveData . Instead of:

 viewModel.codeRequestSuccess.observe(this, object : Observer<Boolean> { override fun onChanged(t: Boolean?) { if (t != null && t == true) { view?.findNavController()?.navigate(R.id.action_forgotPasswordFragment_to_resetCodeFragment) } } }) 

I designed the handler in a separate class property:

 private val listener:Observer<Boolean> = object : Observer<Boolean> { override fun onChanged(t: Boolean?) { if (t != null && t == true) { view?.findNavController()?.navigate(R.id.action_forgotPasswordFragment_to_resetCodeFragment) } } } .... viewModel.codeRequestSuccess.observe(this, listener) 

So it all worked.