OnCreateOptionsMenu(), вызываемый дважды в фрагменте

У меня есть простое приложение с меню опций, которое меняется в начале фрагментов. Проблема в том, что в начале все фрагменты, кроме первого onCreateOptionsMenu(), вызываются дважды - внутри onCreate() и after onResume(). В onCreate() я называю это вручную через setHasOptionsMenu (true), но после onResume() этого не должно произойти. Кроме того, это происходит только после начала первого фрагмента.

Вот код базовых фрагментов:

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

И изменение кода фрагментов в Activity:

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

Образец не использует внешнюю библиотеку, такую ​​как ActionBarSherlock, только SupportLibrary. Я полагаю, проблема заключается в методе FragmentTransaction replace(), потому что он отлично работает, когда начинается первый фрагмент. Но я не знаю, с чего начать решать проблему. Мне нужно точно заменить фрагмент в представлении.

Ответ 1

Я знаю, что опаздываю на вечеринку, но столкнулся с той же проблемой, и моим решением было явно добавить

setHasOptionsMenu(false);

к моей функции SupportFragments onCreate. Это предотвращает любые дополнительные вызовы для действий onCreateOptionsMenu и onPrepareOptionsMenu. Надеюсь, это поможет.

Ответ 2

Я предполагаю, что вновь добавленный фрагмент снова вызывает действия onCreateOptionsMenu!

1 > Попробуйте добавить

setRetainInstance (истина);

для создания фрагмента!

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

Это спасет/восстановит отдельные состояния каждого из фрагментов при вращении

Проблема, по-видимому, связана с тем, что Android не уничтожает фрагмент, когда действие уничтожается (когда устройство повернуто).

Я нашел это здесь Джейк Уортон в SO

Обновление: 2 > Другой способ - не добавлять фрагменты в файл макета, а также создавать их вручную, вызывая метод constructor/newInstance.

Если вы добавите фрагмент в макет, инфраструктура android создаст его для вас. Вместо того, чтобы вручную создавать фрагменты, вы должны получить его экземпляр, вызвав FragmentManager.getFragmentById и вместо этого используйте этот экземпляр.

Поэтому всегда указывайте идентификатор и/или тег для ваших фрагментов

3 > Попробуйте это, вызвав menu.clear()

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

     }

Ответ 3

Самый простой способ решить проблему - очистить меню перед его завышением.

menu.clear() очистит любое существующее меню и начнет со следующего.

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

Ответ 4

Возможно, вы можете попробовать это следующим образом:

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

т.е. проверьте, существует ли в меню один из ваших пунктов меню, а если нет, возможно, все они должны быть добавлены.

Ответ 5

Если вы не обрабатываете элемент меню, вы должны вызвать реализацию суперкласса onOptionsItemSelected() (реализация по умолчанию возвращает false).

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    return super.onOptionsItemSelected(item);
}