Emmanuel Mtali
Emmanuel Mtali

Reputation: 4963

Handle back pressed on fragment then continue navigating

I am listening back button pressed on my fragment as follows

val callback = requireActivity().onBackPressedDispatcher.addCallback(this) {
    podcastViewModel.removePodcast();
    // THEN - continue navigating 
}

How can I perform a task like removePodcast(); then after continue navigation to back. The above code intercept back button pressed but doesn't continue

Upvotes: 3

Views: 9860

Answers (5)

Deepu George Jacob
Deepu George Jacob

Reputation: 474

You can do like this.

requireActivity().onBackPressedDispatcher.addCallback(object :OnBackPressedCallback(true) {
        override fun handleOnBackPressed() {
            // Add you code for the hardware back
        }
    })

Upvotes: 1

Waqar Younas
Waqar Younas

Reputation: 1

override fun getOnBackInvokedDispatcher(): OnBackInvokedDispatcher {
    onBackPressedDispatcher.addCallback {
        if (enableBackPress) {
            //Do your operation here
        } else {
            toast("Please wait...")
        }
    }
    return super.getOnBackInvokedDispatcher()
}

Upvotes: 0

Rakib Hasan
Rakib Hasan

Reputation: 171

Try this one!

override fun onAttach(context: Context) {
    super.onAttach(context)
    val callback: OnBackPressedCallback = object :
        OnBackPressedCallback(true) {
        override fun handleOnBackPressed() {
            podcastViewModel.removePodcast();
            this.remove()
            activity?.onBackPressed()
        }
    }
    requireActivity().onBackPressedDispatcher.addCallback(this, callback)
}

Upvotes: 1

cactustictacs
cactustictacs

Reputation: 19534

You're overriding the usual back-pressed behaviour, which is why it doesn't navigate back. You need to call parentFragmentManager.popBackStack() (or findNavController().popBackStack() if you're using the Navigation component).

Your other option is to do setEnabled = false in the callback after you remove your podcast (meaning the handler won't be called next time) and then immediately fire a back-pressed event with activity?.onBackPressed(). That will handle it with the default behaviour (unless you've added more dispatchers! In which case it'll fall through to the next one)


edit: I've used the popBackStack stuff myself, but it might be a better idea to use the "disable dispatcher and re-fire" approach in general. Purely because the standard behaviour could possibly change (a lot is going on with back stacks and navigation development) so hardcoding a popBackStack call might lead to problems down the line.

I don't know what the official line is though - the docs have this to say:

Changing the enabled state on the OnBackPressedCallback is strongly recommended for temporary changes as it maintains the ordering described above, which is particularly important if you have callbacks registered on multiple different nested lifecycle owners.

but that's more about changing the response to a back press temporarily, not handling one press and messing around, firing multiple events to generate a particular standard behaviour

Upvotes: 7

Emmanuel Mtali
Emmanuel Mtali

Reputation: 4963

Just found a way! The callback should be disabled or removed

val callback = requireActivity().onBackPressedDispatcher.addCallback(this) {
    podcastViewModel.removePodcast();
    this.remove()
    activity?.onBackPressed()
}

Upvotes: 2

Related Questions