terrakok/Cicerone

BackTo not working for activities

ITurchenko opened this issue · 5 comments

BackTo command doesn't work for activities in history stack.

Let's say we have Screen1 - Activity1, Screen2 - Activity2 and Screen3 - Activity3

router().newRootChain(Screen1,Screen2,Screen3)

Now we want go back from Screen3 to Screen2
But router().backTo(Screen2) will not work at all! Because backTo() method in AppNavigator works only with fragments!

Hi I'm facing the same situation yesterday, and I found that not only BackTo(), but also NavigateTo() function is not working on Activities in route tree. In this situation, I'm trying to use fragments and avoid activities in my projects.
I have one idea that might solve the problem but may have some performance issues (I haven't test it yet).
We can use an empty fragment as bridge to link the route tree and activities, between this fragment and activities we use startActivityForResult() and onActivityResult() to pass parameters to control routes. In this way, because the empty fragment it self is in the route tree, we can use BackTo and NavigateTo functions to implement navigation, and there is no need to directly add activities into the route tree.
Also it might be required to set the activities' launch mode to single task.

Any way, I still think that it would be great to let BackTo and NavigateTo available for activities.

I think replace also doesn't work for activities

Yes, this library doesn't support full featured navigation for activities because there isn't way to manipulate activities stack directly

Just interesting why using Intent.FLAG_ACTIVITY_CLEAR_TOP when creating intent to go back to ActivityScreen is not a solution?

class MyNavigator(activity: FragmentActivity, containerId: Int) : AppNavigator(
    activity = activity,
    containerId = containerId
) {
    override fun backTo(command: BackTo) {
        if (command.screen is ActivityScreen) {
            backToActivity(command.screen as ActivityScreen)
        } else {
            super.backTo(command)
        }
    }

    private fun backToActivity(screen: ActivityScreen) {
        val activityIntent = screen.createIntent(activity)
            .apply {
                addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
            }
        try {
            activity.startActivity(activityIntent, screen.startActivityOptions)
        } catch (e: ActivityNotFoundException) {
            unexistingActivity(screen, activityIntent)
        }
    }
}

If there isn't the screen in the stack new screen will be launched