Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FragmentStatePageAdapter duplicates ActionBar menu items

I have a problem with FragmentStatePageAdapter (that I use as adapter for a ViewPager) and the menu items from the action bar.

When I launch the application, everything is fine. If I move the task to background (for example, pressing HOME button) and I start doing stuff until the activity is ended, then when I go back to my application (through the launcher or a notification I create) everything is fine except there are duplicated menu items in the action bar.

An important detail is that the only duplicated items are those that are created in the onCreateOptionsMenu() of each fragment I use in the ViewPager.

If I replaceFragmentStatePageAdapter with FragmentPageAdapter the items are not duplicated anymore, but the fragments are not shown in the ViewPager (getItem() function from the adapter is never called so it does not return any fragment).

Any ideas? A way to avoid FragmentStatePageAdapter to duplicate menu items? Maybe use FragmentPageAdapter but with a modification to show the fragments? A modification in my fragments?

Here are some code snippets from my application...

How menu items are created inside the fragments:

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    /* Create play button */
    final MenuItem mPlay = menu.add(R.string.play_all);

    mPlay.setIcon(R.drawable.ic_play_all);
    mPlay.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);

    mPlay.setOnMenuItemClickListener(new OnMenuItemClickListener() {
        @Override
        public boolean onMenuItemClick(MenuItem item) {
            final List<Song> songs = getSongs();

            if (songs.size() == 0) {
                /* Show message */
                Toast.makeText(mContext, R.string.no_song_list, Toast.LENGTH_LONG).show();
            } else {
                /* Play song list */
                try { PlayManager.getService().playList(songs); } catch (Exception e) {}
            }

            return false;
        }
    });

    /* Create menu */
    super.onCreateOptionsMenu(menu, inflater);
}

How fragments are instantiated in the ViewPager adapter

@Override
public Fragment getItem(int position) {
    final Class<?> cls = mTabs.get(position);

    /* No tab */
    if (cls == null)
        return null;

    /* Instantiate fragment */
    final Fragment fragment = Fragment.instantiate(mContext, cls.getName(), null);

    /* Add to list */
    mFragments.put(position, fragment);

    /* Return fragment */
    return fragment;
}

Thanks!

PS: I tried to change the launchMode of the activity to "singleTop" and I also tried to return in getItem() the previosly created fragment (but that's useless as getItem() is never called when I return to the application, as I said before).

like image 737
Miguel Botón Avatar asked May 07 '12 15:05

Miguel Botón


Video Answer


2 Answers

I found a solution to my problem a few days after posting my problem. I'm sorry for putting it here so late.

The following code fixed my problem:

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    outState.remove("android:support:fragments");
}

As simple as writing that piece of code in the activity where I instantiate and use the fragments.

I hope this helps :)

like image 92
Miguel Botón Avatar answered Oct 03 '22 05:10

Miguel Botón


Before inflating the options menu in your Fragment inside the ViewPager, check whether the Fragment instance is visible to prevent duplicated menu items:

// This should be in your Fragment implementation
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
{
    if(isVisible())
    {
        inflater.inflate(R.menu.menu_fragment, menu);
    }
    super.onCreateOptionsMenu(menu, inflater);
}
like image 30
Márton Avatar answered Oct 03 '22 03:10

Márton