【问题标题】:onCreateOptionsMenu() called twice in FragmentonCreateOptionsMenu() 在 Fragment 中调用了两次
【发布时间】:2020-04-28 22:44:58
【问题描述】:

我有一个带有选项菜单的简单应用程序,它在片段开始时会发生变化。 问题是,在开始时,除了第一个 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);
    }
}

以及Activity中不断变化的片段代码:

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

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

【问题讨论】:

  • 您使用的是哪款手机?如果手机有一个专用的菜单按钮,onCreateOptionsMenu 只会在用户点击它时被调用。对于附加组件,setHasOptionsMenu(true) 不必须调用 onCreateOptionsMenu。它只是通知框架在填充菜单时片段想要参与。
  • 当我遇到同样的问题时,OP 甚至不允许我添加/编辑问题。我知道关于菜单的基本知识,问题很奇怪,就像 OP 描述的那样。编辑:我正在使用嵌套片段
  • @prijupaul 它实际上仅适用于预蜂窝版本。在 Honeycomb 和之后的 onCreateOptionsMenu 将在您调用 setHasOptionsMenu() 后立即调用。
  • @Zyoo 我写的代码完全重现了这个错误。我以为我在某处犯了错误,所以用最少的代码创建了一个新项目。我还没有找到解决方案,必须更改代码,使其独立于此类行为。
  • 好吧,好吧,我们有不同的问题或相同的问题,我会再给一些测试用例

标签: android android-fragments android-optionsmenu


【解决方案1】:

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

setHasOptionsMenu(false);

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

【讨论】:

    【解决方案2】:

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

    menu.clear() 将清除所有现有菜单,并从新菜单开始。

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

    【讨论】:

      【解决方案3】:

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

      1>尝试添加

      setRetainInstance(true);

      到片段构造函数!

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

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

      这个问题似乎与android在activity销毁时(设备旋转时)没有销毁fragment有关。

      我在这里找到了这个Jake Wharton 在 SO

      更新: 2>另一种方法是避免在布局文件上添加片段,并且通过调用构造函数/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);
      
           }
      

      【讨论】:

      • 不,我不认为这是答案。当然,我尝试了你上面所说的一切,但每次我测试它都会发生这种情况
      • @Zyoo 有其他解决方案吗?
      • 对不起,不,我决定不使用 optionmenu,但我认为将来会需要它,所以我仍在尝试
      【解决方案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】:

        使用menu?.clear() 是一种解决方法。在使用之前,请确保您没有从MainActivity 重新创建片段。由于配置更改、应用程序长时间处于后台等原因,在重新创建应用程序时,活动和片段会自动重新创建。所以,从MainActivity 我们不需要再次创建MyFragment

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

        如果您不检查,片段将在活动重新创建时再次添加。因此,工具栏会有重复的菜单选项。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-10-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多