Search code examples
androidkotlinandroid-fragmentsandroid-architecture-navigation

Can't go back using the back button after navigating from a specific fragment to another


In my app have a navigation flow like this

AuthFragment --> SellerMainScreenFragment -----> pay_nav_graph (Nested Graph)
                                    |
                                    |----> CreditFragment---------
                                    |                            |
                                    |----> CreditAddFragment <---|
                                                            |
                                                            |-------> TransactionResultFragment

Now when the app try to navigate from SellerMainScreenFragment to CreditAddFragment, everything works fine and upon pressing the back button in the latter fragment, the app returns to the former. The navigation code is

adapter.wasAddBalPressed.observe(viewLifecycleOwner, Observer {
  if (it != NO_VAL)
     findNavController().navigate(SellerMainScreenFragmentDirections.actionSellerListScreenFragmentToCreditAddFragment(it))
})

But when the app navigates from CreditFragment to CreditAddFragment, upon pressing the back button in the CreditAddFragment, the app doesn't return to the previous fragment. The code goes :

val action = CreditFragmentDirections.actionCreditFragmentToCreditAddFragment(viewModel.userSellerPhoneNo)
findNavController().navigate(action)

I have tried setting a custom onBackPressedCallback on the OnBackPressedDispatcher like so

requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner) {
    findNavController().popBackStack()
    remove()
}

But even then it doesn't return to the previous fragment if it is the CreditFragment but in the case of the SellerMainScreenFragment, it works as intended.

I have also correctly set the app:defaultNavHost = true in the NavHostFragment.

At this point I have tried cleaning the project, invalidating the caches, cold booting the emulator and I tried to debug, but even then I can't find anything suspicious.

So if anyone can help out, please try to do so.Thanks.

Edit-1 :-

This is the navigation xml file that I am currently using in the app

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main_nav_host_fragment"
    app:startDestination="@id/authFragment">

    <fragment
        android:id="@+id/authFragment"
        android:name="com.example.paylater.ui.AuthFragment"
        android:label="AuthFragment"
        tools:layout="@layout/fragment_auth">
        <action
            android:id="@+id/action_authFragment_to_sellerListScreenFragment"
            app:destination="@id/sellerListScreenFragment"
            app:popUpTo="@id/authFragment"
            app:popUpToInclusive="true" />
    </fragment>

    <fragment
        android:id="@+id/sellerListScreenFragment"
        android:name="com.example.paylater.ui.SellerMainScreenFragment"
        android:label="SellerListScreenFragment"
        tools:layout="@layout/fragment_main_screen">
        <action
            android:id="@+id/listFragment_to_creditFragment"
            app:destination="@id/creditFragment" />
        <action
            android:id="@+id/action_sellerListScreenFragment_to_pay_nav_graph"
            app:destination="@id/pay_nav_graph" />
        <action
            android:id="@+id/action_sellerListScreenFragment_to_creditAddFragment"
            app:destination="@id/creditAddFragment" />
    </fragment>

    <fragment
        android:id="@+id/creditFragment"
        android:name="com.example.paylater.ui.CreditFragment"
        android:label="CreditFragment"
        tools:layout="@layout/fragment_credit_enter_no">
        <!--<action
            android:id="@+id/action_creditFragment_self"
            app:destination="@id/creditFragment" />-->
        <action
            android:id="@+id/action_creditFragment_to_creditAddFragment"
            app:destination="@id/creditAddFragment" />
    </fragment>


    <fragment
        android:id="@+id/creditAddFragment"
        android:name="com.example.paylater.ui.CreditAddFragment"
        android:label="CreditAddFragment"
        tools:layout="@layout/fragment_credit_add">
        <action
            android:id="@+id/action_creditAddFragment_self"
            app:destination="@id/creditAddFragment" />
        <action
            android:id="@+id/action_creditAddFragment_to_transactionResultFragment"
            app:destination="@id/transactionResultFragment" />
        <argument
            android:name="sellerPhoneNo"
            app:argType="string" />

    </fragment>

    <fragment
        android:id="@+id/transactionResultFragment"
        android:name="com.example.paylater.ui.TransactionResultFragment"
        android:label="TransactionResultFragment"
        tools:layout="@layout/fragment_transaction_result">
        <action
            android:id="@+id/action_transactionResultFragment_self"
            app:destination="@id/transactionResultFragment" />
        <argument
            android:name="sellerPhoneNo"
            app:argType="string" />
    </fragment>

    <action
        android:id="@+id/action_global_sellerListScreenFragment"
        app:destination="@id/sellerListScreenFragment" />

    <navigation
        android:id="@+id/pay_nav_graph"
        app:startDestination="@id/payFragment">

        <argument
            android:name="sellerPhoneNo"
            app:argType="string" />
        <fragment
            android:id="@+id/payFragment"
            android:name="com.example.paylater.ui.PayFragment"
            android:label="PayFragment">
            <argument
                android:name="sellerPhoneNo"
                app:argType="string" />
            <action
                android:id="@+id/action_payFragment_to_processPaymentFragment"
                app:destination="@id/processPaymentFragment" />
            <action
                android:id="@+id/action_payFragment_self"
                app:destination="@id/payFragment" />
        </fragment>
        <fragment
            android:id="@+id/processPaymentFragment"
            android:name="com.example.paylater.ui.ProcessPaymentFragment"
            android:label="ProcessPaymentFragment" />
    </navigation>
</navigation>

Edit-2: Even after explicitly calling

findNavController().popBackStack(R.id.creditFragment, false)

in the onBackPressedCallback, it still doesn't return to the previous fragment (CreditFragment)


Solution

  • So basically the app was observing a MediatorLiveData in the CreditFragment and when it's value changed the navigation to the CreditAddFragment happened.

    But for some reason the MediatorLiveData's value was maintained as it navigated to the next fragment, and upon pressing the back button, the app navigated to the previous fragment, but then navigated again to the CreditAddFragment instantly, leading to it seeming as if the back navigation didm't happen.

    I found this when I put Log statements in both fragments' onViewCreated(), after @MaryJane had suggested looking at the backstack behaviour.

    Then only did I see this strange behaviour. So a big thanks to @MaryJane and for helping me solve this, and sorry to everyone for asking such a question.