这是我的问题。我有一个应用程序,我在其中使用带有选项卡的 ActionBar Sherlock、带有选项菜单的片段。每次我旋转模拟器时,都会为所有片段添加菜单,即使是那些被隐藏/删除的片段(我都试过了)。
这是设置:一个 FragmentActivity,它有一个带有 ActionBar 的
final ActionBar bar = getSupportActionBar();
bar.addTab(bar.newTab()
.setText("1")
.setTabListener(new MyTabListener(new FragmentList1())));
bar.addTab(bar.newTab()
.setText("2")
.setTabListener(new MyTabListener(new FragmentList2())));
bar.addTab(bar.newTab()
.setText("3")
.setTabListener(new MyTabListener(new FragmentList3())));
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
bar.setDisplayShowHomeEnabled(true);
bar.setDisplayShowTitleEnabled(true);
这些选项卡都使用相同的侦听器:
private class MyTabListener implements ActionBar.TabListener {
private final FragmentListBase m_fragment;
public MyTabListener(FragmentListBase fragment) {
m_fragment = fragment;
}
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
FragmentManager fragmentMgr = ActivityList.this.getSupportFragmentManager();
FragmentTransaction transaction = fragmentMgr.beginTransaction();
transaction.add(R.id.frmlyt_list, m_fragment, m_fragment.LIST_TAG);
transaction.commit();
}
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
FragmentManager fragmentMgr = ActivityList.this.getSupportFragmentManager();
FragmentTransaction transaction = fragmentMgr.beginTransaction();
transaction.remove(m_fragment);
transaction.commit();
}
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
}
}
FragmentListBase 的每个子类都有自己的菜单,因此所有 3 个子类都有:
setHasOptionsMenu(true);
和适当的
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
Log.d(TAG, "OnCreateOptionsMenu");
inflater.inflate(R.menu.il_options_menu, menu);
}
当我运行应用程序时,我可以看到 onCreateOptionsMenu 被多次调用,用于所有不同的片段。
我完全被难住了。
我尝试发布尽可能多的代码而不是压倒性的,如果您发现缺少某些内容,请告知。
[编辑] 我添加了更多的日志记录,结果证明片段在旋转时被附加了两次(或更多)。我注意到的一件事是,除了只调用一次的 onCreate() 方法之外,所有内容都被多次调用。
06.704:/WindowManager(72): Setting rotation to 0, animFlags=0
06.926:/ActivityManager(72): Config changed: { scale=1.0 imsi=310/260 loc=en_US touch=3 keys=1/1/2 nav=1/2 orien=L layout=0x10000014 uiMode=0x11 seq=35}
07.374:/FragmentList1(6880): onAttach
07.524:/FragmentList1(6880): onCreateView
07.564:/FragmentList1(6880): onAttach
07.564:/FragmentListBase(6880): onCreate
07.564:/FragmentList1(6880): OnCreateOptionsMenu
07.574:/FragmentList1(6880): OnCreateOptionsMenu
07.604:/FragmentList1(6880): onCreateView
[编辑 2]
好的,我开始追溯 Android 代码并在这里找到了这部分(我为缩短这篇文章而进行了编辑)。
/com_actionbarsherlock/src/android/support/v4/app/FragmentManager.java
public boolean dispatchCreateOptionsMenu(Menu menu, MenuInflater inflater) {
if (mActive != null) {
for (int i=0; i<mAdded.size(); i++) {
Fragment f = mAdded.get(i);
if (f != null && !f.mHidden && f.mHasMenu) {
f.onCreateOptionsMenu(menu, inflater);
}
}
}
问题是 mAdded 确实在其中有多个 FragmentList1 实例,因此 onCreateOptionsMenu() 方法被“正确”调用了 3 次,但是对于 FragmentList1 类的不同实例。我不明白为什么要多次添加该课程……但这是一个很好的线索。