Save the date! Android Dev Summit is coming to Sunnyvale, CA on Oct 23-24, 2019.

Provide custom back navigation

Back navigation is how users move backward through the history of screens they previously visited. All Android devices provide a Back button for this type of navigation, so you should not add a Back button to your app’s UI. Depending on the user’s Android device, this button might be a physical button or a software button.

Android maintains a back stack of destinations as the user navigates throughout your application. This usually allows Android to properly navigate to previous destinations when the Back button is pressed. However, there are a few cases where your app might need to implement its own Back behavior in order to provide the best possible user experience. For example, when using a WebView, you might want to override the default Back button behavior to allow the user to navigate back through their web browsing history instead of the previous screens in your app.

Implement Custom Back Navigation

ComponentActivity, the base class for FragmentActivity and AppCompatActivity, allows you to control the behavior of the Back button by using its OnBackPressedDispatcher, which you can retrieve by calling getOnBackPressedDispatcher().

The OnBackPressedDispatcher controls how Back button events are dispatched to one or more OnBackPressedCallback objects. OnBackPressedCallback defines a single method, handleOnBackPressed(), which responds to a Back button event. This method must return a boolean value indicating whether the event was successfully processed.

Callbacks are added via the addCallback methods. It is strongly recommended to use the addCallback() method which takes a LifecycleOwner. This ensures that the OnBackPressedCallback is only added when the LifecycleOwner is Lifecycle.State.STARTED. The activity also removes registered callbacks when their associated LifecycleOwner is destroyed, which prevents memory leaks and makes it suitable for use in fragments or other lifecycle owners that have a shorter lifetime than the activity.

Here's an example callback implementation:

Kotlin

class MyFragment : Fragment() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // This callback will only be called when MyFragment is at least Started.
        requireActivity().onBackPressedDispatcher.addCallback(this) {
            ...
            true // return true if event was handled
        }
    }
    ...
}

Java

public class MyFragment extends Fragment {

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // This callback will only be called when MyFragment is at least Started.
        requireActivity().getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback() {
            @Override
            public boolean handleOnBackPressed() {
                ...
                return true; // return true if event was handled
            }
        });
    }
    ...
}

You can provide multiple callbacks via addCallback(). When doing so, the callbacks are invoked in the reverse order in which they are added - the callback added last is the first given a chance to handle the Back button event. For example, if you added three callbacks named one, two and three in order, they would be invoked in the order of three, two, and one, respectively.

Callbacks follow the Chain of Responsibility pattern. Each callback in the chain is invoked only if the preceding callback was not able to process the event. This means that in the preceding example, callback two would be invoked only if callback three returned false. Callback one would only be invoked if callback two returned false, and so on.

Note that when added via addCallback(), the callback is not added to the chain of responsibility until the LifecycleOwner enters the Lifecycle.State.STARTED state.

The addCallback methods return a Cancellable object. You can remove a callback at any time by calling cancel() on the returned Cancellable object. This is usually not necessary, however, because callbacks are automatically removed when their associated LifecycleOwner is destroyed.

Activity onBackPressed()

If you are using onBackPressed() to handle Back button events, we recommend using a OnBackPressedCallback instead. However, if you are unable to make this change, the following rules apply:

  • All callbacks registered via addCallback are evaluated when you call super.onBackPressed().
  • onBackPressed is always called, regardless of any registered instances of OnBackPressedCallback.