I am trying to migrate from the deprecated setHasOptionsMenu()/onCreateOptionsMenu() methods to the new addMenuProvider()/onCreateMenu() methods in order to show an options menu from a fragment. Using the new API, I get an ugly delay/flicker of the icons in the action bar when navigating between two fragments that both implement MenuProvider.
I assume this is caused by asynchronous lifecycle callbacks: the new fragment's menu is probably inflated and added just before the old fragment's Lifecycle.Event.ON_DESTROY event triggers the removal of the old menu items, causing a brief moment when both menus are active simultaneously. However, I can't figure out how to avoid this behavior. I have tried calling both removeMenuProvider() and invalidateOptionsMenu() from onDestroyView() in each fragment with no success. I also tried moving addMenuProvider() to onViewCreated() instead of onCreateView(). The issue does not occur with the old setHasOptionsMenu() API.
Minimal reconstruction:
- Open Android Studio, create a new project, and select the "Bottom Navigation Activity" template.
- Create two menu resource files, each containing at least one menu item with an icon and
app:showAsAction="always". - In two of the fragments shown by the bottom navigation controller, call the following from within
onCreateView():
requireActivity().addMenuProvider(object: MenuProvider {
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
menuInflater.inflate(/* one of the menus from step 2 */, menu)
}
override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
return false
}
}, viewLifecycleOwner)
- Run the app and switch between these fragments using the bottom navigation bar. You should see something like this: example gif.