bvitaliyg
bvitaliyg

Reputation: 3245

onCreateOptionsMenu() called twice in Fragment

I have a simple application with options menu, which changing at the start of fragments. The problem is that at the start any fragments except first onCreateOptionsMenu() called twice - within onCreate() and after onResume(). In onCreate() I call it manualy via setHasOptionsMenu(true), but after onResume() it should not happen. Besides, this only occurs after the first fragment started.

Here is base fragments code:

class BaseFragment extends Fragment {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle clicks
        return true;
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        // Create a menu
        super.onCreateOptionsMenu(menu, inflater);
    }
}

And the changing fragments code in Activity:

public void startFragment(BaseFragment fragment) {
    getSupportFragmentManager()
    .beginTransaction()
    .replace(android.R.id.content, fragment)
    .commit();
}

The sample does not use any external library like ActionBarSherlock, only SupportLibrary. I suppose, the problem is in FragmentTransaction replace() method, because it works fine when first fragment is starting. But I don't know, where start to solve the problem. I need exactly replace fragment in View.

Upvotes: 14

Views: 10035

Answers (5)

Damia Fuentes
Damia Fuentes

Reputation: 5493

Using the menu?.clear() is a workaround. Before using that, please make sure you are not recreating the fragment from the MainActivity. On app recreation due to a configuration change, the app being on the background for a long period of time, etc the activities and fragments are recreated automatically. So, from the MainActivity we don't nee to create the MyFragment again.

override fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)
  if (savedInstanceState == null) { // This is what prevents recreating the fragment
    supportFragmentManager
      .beginTransaction()
      .add(R.id.fragment_container, MyFragment())
      .commit()
  }
}

If you don't check that, the fragment will be added again on activity recreation. Therefore, the toolbar will have duplicated menu option items.

Upvotes: 0

capt.swag
capt.swag

Reputation: 10651

The easiest way to solve the issue is to clear the menu just before it's inflated.

menu.clear() will clear any existing menu, and start of with a fresh one.

@Override
 public void   onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
      super.onCreateOptionsMenu(menu, inflater);
      menu.clear();
      inflater.inflate(R.menu.sample_menu, menu);
 }

Upvotes: 8

C0D3LIC1OU5
C0D3LIC1OU5

Reputation: 8680

I know I am late to the party, but ran into the same issue- and my solution was actually to explicitly add

setHasOptionsMenu(false);

to my SupportFragments onCreate function. This prevents any extra calls to activities' onCreateOptionsMenu and to onPrepareOptionsMenu. Hope this helps.

Upvotes: 7

Einar H.
Einar H.

Reputation: 575

You could perhaps try it like this:

    private final int MENU_SEARCH=Menu.FIRST;
:
    @Override public void onPrepareOptionsMenu(Menu menu) {
        if (menu.findItem(MENU_SEARCH)==null) {
            menu.add(0, MENU_SEARCH, Menu.NONE, getText(R.string.menu_search));
:

I.e. check if one of your menu items exists in the menu, and if not, probably all of them need to be added.

Upvotes: 0

LOG_TAG
LOG_TAG

Reputation: 20569

I guess newly added fragment causes the activities onCreateOptionsMenu to be called again!

1>Try Adding

setRetainInstance(true);

to fragment constructor!

 public BaseFragment()
 {
    setRetainInstance(true);
    setHasOptionsMenu(true);
 }

This will save/restore the individual states of each of the fragments upon rotation

The problem seems to be related to the fact that Android does not destroy the fragment when the activity is destroyed (when the device is rotated).

I found this here Jake Wharton in SO

Update: 2>Another way is to avoid adding the fragments on the layout file, and also instantiating them manually by calling the constructor/newInstance method.

If you add a fragment on the layout, the android framework will instantiate it for you. Instead of instantiating the fragments manually, you should retrieve it's instance by calling FragmentManager.getFragmentById and use that instance instead.

So always include an ID and/or a tag for your fragments

3>Try with this by calling menu.clear()

  @Override
     public void   onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
          menu.clear();
          inflater.inflate(R.menu.call_menu, menu);
          super.onCreateOptionsMenu(menu, inflater);

     }

Upvotes: 3

Related Questions