我有一个带有选项菜单的简单应用程序,它在片段的开头变化。 问题是,在开始时除了第一个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()方法中,因为它在第一个片段启动时工作正常。但我不知道,从哪里开始解决问题。我需要在View中完全替换片段。
答案 0 :(得分:7)
我知道我迟到了,但遇到了同样的问题 - 我的解决方案实际上是明确添加
setHasOptionsMenu(false);
到我的SupportFragments onCreate函数。这可以防止对活动的任何额外调用。 onCreateOptionsMenu和onPrepareOptionsMenu。希望这会有所帮助。
答案 1 :(得分:3)
解决问题的最简单方法是在菜单膨胀之前清除菜单。
menu.clear()将清除所有现有菜单,并从新菜单开始。
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
menu.clear();
inflater.inflate(R.menu.sample_menu, menu);
}
答案 2 :(得分:2)
我猜新添加的片段会导致再次调用onCreateOptionsMenu上的活动!
1>尝试添加
setRetainInstance(真);
到片段构造函数!
public BaseFragment()
{
setRetainInstance(true);
setHasOptionsMenu(true);
}
这将在旋转时保存/恢复每个片段的各个状态
这个问题似乎与Android在活动被销毁时(旋转设备时)不破坏碎片的事实有关。
我在SO
中找到了Jake Wharton更新: 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);
}
答案 3 :(得分:0)
你也许可以这样试试:
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));
:
即。检查菜单中是否存在您的某个菜单项,如果不存在,则可能需要添加所有菜单项。
答案 4 :(得分:0)
使用import React, { useEffect } from 'react';
import styled from 'styled-components';
import FoodListItem from '../molecules/FoodListItem';
const rawFoodList = ({className}) => {
const [foodList, setFoodList] = useState([]);
useEffect(() => {
async function fetchFoodList() {
const res = await fetch('api-url');
res.json()
.then(res => setFoodList(res))
.catch(err => console.log(err));
console.log(foodList);
}
fetchFoodList();
})
return (
<ul className={className}>
{foodList.map((food, index) => <FoodListItem key={index} food={food} />)}
</ul>
);
}
const FoodList = styled(rawFoodList)`
width: 100%;
margin: 0;
padding: 0;
`;
export default FoodList;
是一种解决方法。在使用它之前,请确保您没有从menu?.clear()
重新创建片段。在由于配置更改而重新创建应用程序时,应用程序长时间处于后台,等等,活动和片段会自动重新创建。因此,我们不再需要MainActivity
来创建MainActivity
。
MyFragment
如果不进行选择,则将在重新创建活动时再次添加该片段。因此,工具栏将具有重复的菜单选项项。
答案 5 :(得分:-1)
如果你不处理菜单项,你应该调用onOptionsItemSelected()的超类实现(默认实现返回false)。
@Override
public boolean onOptionsItemSelected(MenuItem item) {
return super.onOptionsItemSelected(item);
}