onCreateOptionsMenu()在Fragment中调用两次

bvi*_*iyg 11 android-fragments android-optionsmenu

我有一个带有选项菜单的简单应用程序,它在片段的开头变化.问题是,在开始时除了第一个onCreateOptionsMenu()之外的任何片段都会被调用两次 - 在onCreate()和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);
    }
}
Run Code Online (Sandbox Code Playgroud)

并在Activity中更改片段代码:

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

该示例不使用任何外部库,如ActionBarSherlock,只使用SupportLibrary.我想,问题出在FragmentTransaction的replace()方法中,因为它在第一个片段启动时工作正常.但我不知道,从哪里开始解决问题.我需要在View中完全替换片段.

C0D*_*OU5 7

我知道我迟到了,但遇到了同样的问题 - 我的解决方案实际上是明确添加

setHasOptionsMenu(false);
Run Code Online (Sandbox Code Playgroud)

到我的SupportFragments onCreate函数.这可以防止对活动'onCreateOptionsMenu和onPrepareOptionsMenu的任何额外调用.希望这可以帮助.


cap*_*wag 6

解决问题的最简单方法是在菜单膨胀之前清除菜单。

menu.clear() 将清除任何现有菜单,并从一个新菜单开始。

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


LOG*_*TAG 3

我猜想新添加的片段会导致 onCreateOptionsMenu 活动再次被调用!

1>尝试添加

setRetainInstance(真);

到片段构造函数!

 public BaseFragment()
 {
    setRetainInstance(true);
    setHasOptionsMenu(true);
 }
Run Code Online (Sandbox Code Playgroud)

这将在旋转时保存/恢复每个片段的单独状态

该问题似乎与以下事实有关:当 Activity 被销毁时(当设备旋转时),Android 不会销毁 Fragment。

我在这里找到了杰克·沃顿 ( Jake Wharton )

更新:2>另一种方法是避免在布局文件上添加片段,并通过调用 constructor/newInstance 方法手动实例化它们。

如果您在布局上添加一个片段,Android 框架将为您实例化它。您应该通过调用 FragmentManager.getFragmentById 来检索其实例并使用该实例,而不是手动实例化片段。

因此,请务必为您的片段添加 ID 和/或标签

3>通过调用menu.clear()来尝试这个

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

     }
Run Code Online (Sandbox Code Playgroud)

  • 不,我不认为这是答案。当然,我尝试了上面所说的所有内容,但每次测试时仍然会发生这种情况 (2认同)