Search code examples
androidkotlinnavigation-architecture

Why not work back button with android navigation component


this my Auth Activity

class AuthActivity : AppCompatActivity() {
    private lateinit var navController: NavController
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding = ActivityAuthBinding.inflate(layoutInflater)
        setContentView(binding.root)

        navController = Navigation.findNavController(this, fragment.id)
        NavigationUI.setupActionBarWithNavController(this, navController)

    }

    override fun onSupportNavigateUp(): Boolean {
        return NavigationUI.navigateUp(navController, null)
    }

}

LoginFragment -> if login is success goto "AcceptCodeFragment"

 viewModel.loginResponse.observe(viewLifecycleOwner, { response ->
            viewBinding.pbLogin.visible(response is Resource.Loading)
            when (response) {
                is Resource.Success -> {
                    viewBinding.tvResponse.text = response.value.message
                    val action = LoginFragmentDirections.actionLoginFragmentToAcceptCodeFragment()
                    findNavController().navigate(action)
                }
                is Resource.Error -> if (response.isNetworkError) {
                    requireView().snackBar("Check your connection")
                } else {
                    requireView().snackBar(response.errorBody.toString())
                }
            }

in AcceptCodeFragment Back button not work.

Two fragments using same viewmodel.


Solution

  • Your issue is not with the back button not working, it is that LiveData is for state, not events like your loginResponse. As LiveData is for events, it redelivers the previous response when you go back to your LoginFragment. This then triggers your navigate() call again, pushing you right back to your AcceptCodeFragment.

    As per the LiveData with SnackBar, Navigation, and other events blog post, LiveData cannot be directly used for events. Instead, you should consider using an event wrapper or another solution (such as a Kotlin Flow) that allow your events to only be handled once.