14

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.

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
bvitaliyg
  • 3,155
  • 4
  • 30
  • 46
  • Which phone are you using? If the phone has a dedicate menu button, onCreateOptionsMenu will be invoked only when the user clicks on it. To add-on it is not mandatory that setHasOptionsMenu(true) should call onCreateOptionsMenu. It just informs the framework that the fragment would like to participate when populating menu. – prijupaul Sep 25 '13 at 06:08
  • OP doesn't even let me add/edit the question when i have the same problem. I know the basic stuffs about Menu, the problem is weird like OP described. EDIT: i'm using nested fragment – Zyoo Sep 25 '13 at 08:35
  • @prijupaul it's actually only for pre-Honeycomb versions. On Honeycomb and later onCreateOptionsMenu will be invoked immediately after you call setHasOptionsMenu(). – bvitaliyg Sep 25 '13 at 15:10
  • @Zyoo the code that I wrote exactly reproduces the bug. I thought I made ​​a mistake somewhere, so created a new project with a minimum of code. I have not found a solution, had to alter the code so that it is independent to such behavior. – bvitaliyg Sep 25 '13 at 15:17
  • well, okay either we have different problem or the same, i will give some testcases again – Zyoo Sep 25 '13 at 15:52
  • @bvitaliyg : I did a sample app with ICS (Nexus phone) and JB versions (Nexus 7 tablet). onCreateOptionsMenu gets invoked only when I press the Menu button though I setHasOptionsMenu in onCreate. – prijupaul Sep 25 '13 at 22:05
  • Solved my problems: http://stackoverflow.com/questions/18768021/menu-inflating-calls-multiple-times-at-fragments-oncreateoptionsmenu – Franklin Hirata Nov 25 '15 at 01:30

5 Answers5

8

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);
 }
capt.swag
  • 10,335
  • 2
  • 41
  • 41
7

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.

C0D3LIC1OU5
  • 8,600
  • 2
  • 37
  • 47
3

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);

     }
Community
  • 1
  • 1
LOG_TAG
  • 19,894
  • 12
  • 72
  • 105
  • 2
    nope, i don't think it's the answer. of course i tried all you said above but still it happens everytime i test it – Zyoo Sep 25 '13 at 08:33
  • @Zyoo got any other solution for your problem ? – LOG_TAG Nov 20 '13 at 06:27
  • sorry, no, i've decided to not using optionmenu, but i think in the future it'll be needed, so i'm still trying – Zyoo Nov 20 '13 at 14:51
0

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.

Einar H.
  • 575
  • 5
  • 5
0

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.

Damia Fuentes
  • 5,308
  • 6
  • 33
  • 65