KaustubhPatange / navigator

A small navigation library for Android to ease the use of fragment transactions & handling backstack (also available for Jetpack Compose).
Apache License 2.0
99 stars 5 forks source link

Crashes if call goBack() after navigateTo() #29

Open nvhaiwork opened 11 months ago

nvhaiwork commented 11 months ago

Case: Fragment1 navigateTo() Fragment2 Fragment2 check condition, if data is invalid -> backTo() Fragment1 => crashes

It works if I use Handle.postDelay()

Fragment 1 Code: onViewCreated()

     getView()?.findViewById<TextView>(R.id.text)?.setOnClickListener {
        getView()?.findViewById<TextView>(R.id.text)?.text = "Clicked"
        val options = FragmentNavigator.NavOptions(
            transaction = FragmentNavigator.TransactionType.REPLACE,
            animation = AnimationDefinition.Zoom
        )
        (activity as MainActivity).navigate.navigateTo(Fragment2(),options)
    }

Fragment 2 code: onViewCreated()

     getView()?.findViewById<TextView>(R.id.text)?.setOnClickListener {
        getView()?.findViewById<TextView>(R.id.text)?.text = "Clicked"
        val options = FragmentNavigator.NavOptions(
            transaction = FragmentNavigator.TransactionType.ADD,
            animation = AnimationDefinition.Zoom
        )
        (activity as MainActivity).navigate.navigateTo(Fragment3(),options)
    }

    //Handler().postDelayed({
        (activity as MainActivity).navigate.goBack()
    //}, 1)
KaustubhPatange commented 11 months ago

Fragment transactions are async i.e they are executed using a message queue system. APIs like commit, popBackStack adds a new event to be executed later whenever FragmentManager is free.

There are so-called sync APIs like commitNow, popBackStackImmediate that are not queued but are executed immediately upon called. goBack uses popBackStackImmediate API (I don't remember why I used it but maybe my tests would know why). Whenever any other transaction is in progress and these sync APIs are called they crash with a message "Already executing transactions... something like this".

To fix it, use the async FragmentManager.popBackStack API directly. Navigator does not expose a sync version of goBack.