Zhuinden / simple-stack

[ACTIVE] Simple Stack, a backstack library / navigation framework for simpler navigation and state management (for fragments, views, or whatevers).
Apache License 2.0
1.36k stars 75 forks source link

when press the back button, it execute twice and then exit the app #245

Closed Jackyaung closed 3 years ago

Jackyaung commented 3 years ago

I set three tab, when go to tab2.1 from tab2, and then press the back button, it goes back first then exit the app (seems it execute twice), I'm new to android and especially navigation, anyone knows what the problem is ?

Zhuinden commented 3 years ago

The last time I saw this happen to someone, the issue was that they called both if(Navigator.onBackPressed(context)) { AND backstack.goBack() (even though only the first is needed).

For further analysis I'd need to see your Activity's onBackPressed's source code

Jackyaung commented 3 years ago

Hi @Zhuinden sorry to reply late. here are my homeActicity:

class HomeActivity: BaseActivityWithBinding(), SimpleStateChanger.NavigationHandler {

private lateinit var fragmentStateChanger: DefaultFragmentStateChanger

private lateinit var viewModel: HomeViewModel

override fun onCreated(savedInstanceState: Bundle?) {

    fragmentStateChanger = DefaultFragmentStateChanger(supportFragmentManager, R.id.container)

    Navigator.configure()
        .setScopedServices(DefaultServiceProvider())
        .setStateChanger(SimpleStateChanger(this))
        .install(this, findViewById(R.id.container), History.of(RootScreen()))

    val factory = HomeViewModelFactory()
    viewModel = ViewModelProviders.of(this, factory).get(HomeViewModel::class.java)
    binding.lifecycleOwner = this
}
override fun onBackPressed() {
    if (Navigator.onBackPressed(this))
        super.onBackPressed()
}

override fun onNavigationEvent(stateChange: StateChange) {
    fragmentStateChanger.handleStateChange(stateChange)
}

override fun initListeners() {
    super.initListeners()
}

}


I write the custom back button and call it at the sub page, it works , but if I press the android back button, it first goes back to previous page and then exit the app

image

Jackyaung commented 3 years ago

@Zhuinden I think I solved it, I just change to below:

override fun onBackPressed() {

// if (Navigator.onBackPressed(this)){ // super.onBackPressed() // }

    Navigator.onBackPressed(this)

}
Zhuinden commented 3 years ago

That doesn't look right, if you do this then you won't exit the app at all.

I believe what you are looking for is to try to dispatch the back event to the Fragment where the custom back behavior is needed, instead of immediately trying to navigate back using Simple-Stack (as the fragment wants to switch tab first).

For that, I used to use findFragmentByTag to check if the Fragment has BackHandler interface and then called goBack() and then returned if it was return true, but now you can actually use requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, object: Callback { }) from AndroidX to intercept back, too.

Zhuinden commented 3 years ago

Have you had any success with resolving this?

I'm kinda stumped as to what's happening on your side, apart from that tab switching is something you need to track yourself. I used onBackPressedDispatcher for this now the other day because I could now.

Jackyaung commented 3 years ago

Hi @Zhuinden thanks for your info, that is very nice of you.

where should I use onBackPressedDispatcher ? what you mean is , i need to use findFragmentByTag to find the Backhandler in every second lever of fragment , and then call requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, object: Callback { }) ?

Zhuinden commented 3 years ago

need to use findFragmentByTag to find the Backhandler in every second lever of fragment

You don't need that if you use the requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, object: Callback { })

Zhuinden commented 3 years ago

I'm just now realizing a flaw in how the back press dispatcher works in ComponentActivity.

I opened an issue for it.

https://github.com/Zhuinden/simple-stack/issues/248

Do you think this is the cause of your issue?

ibrahimyilmaz commented 3 years ago

@Zhuinden I think I solved it, I just change to below:

override fun onBackPressed() {

// if (Navigator.onBackPressed(this)){ // super.onBackPressed() // }

    Navigator.onBackPressed(this)

}

onBackPressed code doesn't seem right when we compared to the example in the readme.

Example

override fun onBackPressed() {
        if (!Navigator.onBackPressed(this)) {
            super.onBackPressed()
        }
    }

Given

override fun onBackPressed() {
    if (Navigator.onBackPressed(this))
        super.onBackPressed()
}

Given code should execute twice

I set three tab, when go to tab2.1 from tab2, and then press the back button, it goes back first then exit the app (seems it execute twice), I'm new to android and especially navigation, anyone knows what the problem is ?

Zhuinden commented 3 years ago

Normally you'd need the !

ibrahimyilmaz commented 3 years ago

@Zhuinden exactly! That's exactly what @Jackyaung is missing in his code. So you can close this issue @Zhuinden.

Zhuinden commented 3 years ago

Nice, glad to see it resolved