Migrate your Old onCreateOptionsMenu to new MenuProvider

Sakhawat Hossain
3 min readJun 28, 2023

As Android continues to evolve, we are presented with new approaches and tools to enhance our app development process. One such notable change is the transition from the traditional onCreateOptionsMenu method to the more flexible and powerful MenuProvider approach. In this article, we will explore the benefits of using MenuProvider and provide step-by-step implementation guidance. So lets dive into the detail part.

Recently, I was trying to implement toolbar menu for my latest pet project(an NFT Android App). When I tried to override the previously used onCreateOptionsMenu, it was showing indication about the deprecation of this override method. Which is why, I had to do some research about implementing the new MenuProvider and MenuHost implementation. We will go through step by step implementation.

By following these steps, you can successfully implement the transition from onCreateOptionsMenu to MenuProvider in your Android application. This change brings increased flexibility and modularity to your menu handling code, allowing for easier maintenance and a more streamlined user experience.

Implementation

Lets create a menu first

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">

<item
android:id="@+id/navigation_wallet"
android:icon="@drawable/ic_wallet"
app:showAsAction="always"
android:title="@string/title_wallet" />

<item
android:id="@+id/navigation_notifications"
android:icon="@drawable/ic_notification"
app:showAsAction="always"
android:title="@string/title_notifications" />

</menu>

Here we have two toolbar menu icons. As we have the menu, now we can use it in our fragment or activity. The implementation of fragment or activity differs a little bit. Lets see it step by step.

Fragment Implementation

(requireActivity() as MenuHost).addMenuProvider(object : MenuProvider {
override fun onPrepareMenu(menu: Menu) {
super.onPrepareMenu(menu)
}

override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
menuInflater.inflate(R.menu.home_menu, menu)
}

override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
return when(menuItem.itemId){
R.id.navigation_notifications -> {
true
}
R.id.navigation_wallet -> {
true
}
else -> false
}
}
}, viewLifecycleOwner, Lifecycle.State.RESUMED)

Here, you can see that we have to use requireActivity() as our menu host. We will be describing about MenuHost and MenuProvider in details soon. Lets migrate the code first.

Activity Implementation

addMenuProvider(object : MenuProvider {
override fun onPrepareMenu(menu: Menu) {
super.onPrepareMenu(menu)
}

override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
menuInflater.inflate(R.menu.home_menu, menu)
}

override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
return when(menuItem.itemId){
R.id.navigation_notifications -> {
true
}
R.id.navigation_wallet -> {
true
}
else -> false
}
}
}, viewLifecycleOwner, Lifecycle.State.RESUMED)

The implementation of activity just differs on having the require activity as the menu host.

Understanding the MenuHost and MenuProvider

MenuProvider which is an interface that mostly has the similar methods compare to the previous ones.

public interface MenuProvider {

default void onPrepareMenu(@NonNull Menu menu) {}

void onCreateMenu(@NonNull Menu menu, @NonNull MenuInflater menuInflater);

boolean onMenuItemSelected(@NonNull MenuItem menuItem);

default void onMenuClosed(@NonNull Menu menu) {}
}

So we can have the previous availed functionalities with the new menu provider with more concise ways.

Now if we see the MenuHost code, we can see that its also an interface that exposes few methods to be overrided. MenuHost comes handy whenever we try to implement new MenuProvider for fragment only.

public interface MenuHost {

void addMenuProvider(@NonNull MenuProvider provider);

void addMenuProvider(@NonNull MenuProvider provider, @NonNull LifecycleOwner owner);

@SuppressLint("LambdaLast")
void addMenuProvider(@NonNull MenuProvider provider, @NonNull LifecycleOwner owner,
@NonNull Lifecycle.State state);

void removeMenuProvider(@NonNull MenuProvider provider);

void invalidateMenu();
}

Conclusion

The transition from onCreateOptionsMenu to MenuProvider represents a significant improvement in menu handling for us. By adopting MenuProvider, we can gain greater flexibility, code modularity, and a streamlined approach to managing menus in their applications. With the step-by-step implementation guide provided in this article, one can seamlessly transition to MenuProvider and leverage its benefits to create more dynamic and user-friendly menus.

Remember, as we embrace new approaches like MenuProvider, it's essential to stay updated with the latest advancements in Android development, enabling us to build better apps and deliver exceptional user experiences.

Thanks for reading.Hope these helps!

--

--

Sakhawat Hossain

Senior Software Engineer | Android | iOS | Java | Kotlin | Flutter