简体   繁体   English

onCreateOptionsMenu() 在 Fragment 中调用两次

[英]onCreateOptionsMenu() called twice in Fragment

I have a simple application with options menu, which changing at the start of fragments.我有一个带有选项菜单的简单应用程序,它在片段的开头发生变化。 The problem is that at the start any fragments except first onCreateOptionsMenu() called twice - within onCreate() and after onResume().问题是在开始时,除了第一次 onCreateOptionsMenu() 调用两次之外的任何片段 - 在 onCreate() 内和 onResume() 之后。 In onCreate() I call it manualy via setHasOptionsMenu(true), but after onResume() it should not happen.在 onCreate() 中,我通过 setHasOptionsMenu(true) 手动调用它,但在 onResume() 之后它不应该发生。 Besides, this only occurs after the first fragment started.此外,这只发生在第一个片段开始之后。

Here is base fragments code:这是基本片段代码:

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

And the changing fragments code in Activity:以及 Activity 中不断变化的片段代码:

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

The sample does not use any external library like ActionBarSherlock, only SupportLibrary.该示例不使用任何外部库,如 ActionBarSherlock,仅使用 SupportLibrary。 I suppose, the problem is in FragmentTransaction replace() method, because it works fine when first fragment is starting.我想,问题出在 FragmentTransaction replace() 方法中,因为它在第一个片段开始时工作正常。 But I don't know, where start to solve the problem.但我不知道,从哪里开始解决问题。 I need exactly replace fragment in View.我需要在视图中完全替换片段。

I know I am late to the party, but ran into the same issue- and my solution was actually to explicitly add我知道我参加聚会迟到了,但遇到了同样的问题-我的解决方案实际上是明确添加

setHasOptionsMenu(false);

to my SupportFragments onCreate function.到我的 SupportFragments onCreate 函数。 This prevents any extra calls to activities' onCreateOptionsMenu and to onPrepareOptionsMenu.这可以防止对活动的 onCreateOptionsMenu 和 onPrepareOptionsMenu 的任何额外调用。 Hope this helps.希望这可以帮助。

The easiest way to solve the issue is to clear the menu just before it's inflated.解决问题的最简单方法是在菜单膨胀之前清除菜单。

menu.clear() will clear any existing menu, and start of with a fresh one. menu.clear() 将清除任何现有菜单,并从一个新菜单开始。

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

I guess newly added fragment causes the activities onCreateOptionsMenu to be called again!我猜新添加的片段会导致活动 onCreateOptionsMenu 再次被调用!

1>Try Adding 1>尝试添加

setRetainInstance(true); setRetainInstance(true);

to fragment constructor!片段构造函数!

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

This will save/restore the individual states of each of the fragments upon rotation这将在旋转时保存/恢复每个片段的各个状态

The problem seems to be related to the fact that Android does not destroy the fragment when the activity is destroyed (when the device is rotated).问题似乎与Android在活动被销毁时(设备旋转时)不会销毁片段有关。

I found this here Jake Wharton in SO我在这里找到了这个Jake Wharton在 SO

Update: 2>Another way is to avoid adding the fragments on the layout file, and also instantiating them manually by calling the constructor/newInstance method.更新:2>另一种方法是避免在布局文件中添加片段,并通过调用构造函数/newInstance 方法手动实例化它们。

If you add a fragment on the layout, the android framework will instantiate it for you.如果你在布局上添加一个片段,android 框架会为你实例化它。 Instead of instantiating the fragments manually, you should retrieve it's instance by calling FragmentManager.getFragmentById and use that instance instead.您应该通过调用 FragmentManager.getFragmentById 并使用该实例来检索它的实例,而不是手动实例化片段。

So always include an ID and/or a tag for your fragments所以总是为你的片段包含一个 ID 和/或标签

3>Try with this by calling menu.clear() 3>通过调用 menu.clear() 试试这个

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

     }

You could perhaps try it like this:你也许可以这样尝试:

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

Ie check if one of your menu items exists in the menu, and if not, probably all of them need to be added.即检查菜单中是否存在您的菜单项之一,如果不存在,则可能需要添加所有菜单项。

Using the menu?.clear() is a workaround .使用menu?.clear()是一种解决方法 Before using that, please make sure you are not recreating the fragment from the MainActivity .在使用之前,请确保您没有从MainActivity重新创建片段。 On app recreation due to a configuration change, the app being on the background for a long period of time, etc the activities and fragments are recreated automatically.在由于配置更改而重新创建应用程序时,应用程序长时间处于后台等,活动和片段会自动重新创建。 So, from the MainActivity we don't nee to create the MyFragment again.因此,从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()
  }
}

If you don't check that, the fragment will be added again on activity recreation.如果您不检查,将在活动娱乐时再次添加该片段。 Therefore, the toolbar will have duplicated menu option items.因此,工具栏将具有重复的菜单选项项。

If you don't handle the menu item, you should call the superclass implementation of onOptionsItemSelected() (the default implementation returns false). 如果不处理菜单项,则应调用onOptionsItemSelected()的超类实现(默认实现返回false)。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM