Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fragment's menu items are added multiple times

I have one activity with exactly one fragment in it. The fragment adds one item to the activity's action bar.

Now when the app runs some time, the user leaves it to do other stuff and returns to the app, there is an additional menu item (i.e. the fragment's item added again). From two item we get three, four, five and so on.

How is it possible that the fragment's menu item is added multiple times?

activity

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

    setContentView(R.layout.activity_conversations_list);
    mToolbar = Ui.setupActionbar(this, false);

    FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
    fragmentTransaction.add(R.id.contentframe, new ConversationsFragment());
    fragmentTransaction.commit();
}

fragment

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

    // has it's own actionbar items
    setHasOptionsMenu(true);
}

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

appbar_menu_conversations_list.xml

<?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/action_refresh"
        android:title="@string/action_sync"
        app:showAsAction="always"
        android:icon="@drawable/ic_sync_white_24dp"/>
</menu>
like image 606
Simon Warta Avatar asked Nov 27 '15 15:11

Simon Warta


1 Answers

You are actually adding the Fragment to the activity multiple times, so it gets multiple menu items. Since the Activity's FragmentManager stores its state on rotation, you need to only add the Fragment in onCreate the first time. You can confirm this by rotating the device and seeing new items added (rotation isn't the only way it'll happen, but an easy one to reproduce).

To do this, simple wrap the Fragment transaction in a test:

if (savedInstanceState == null) {
    FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
    fragmentTransaction.add(R.id.contentframe, new ConversationsFragment());
    fragmentTransaction.commit();
}

After the first time the activity is created, on things like orientation changes, savedInstanceState will be a bundle, but the first time it will be null, so that's a good way to check that things only happen once.

like image 197
rharter Avatar answered Nov 18 '22 18:11

rharter