将项目添加到Fragment中的操作栏选项菜单后,进行方向更改后发生崩溃

我使用ActionBarSherlock和ViewPagerIndicator作为选项卡显示碎片。 其中一个碎片添加项目到ActionBar:

private String[] mapNames; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setHasOptionsMenu(true); // init an String array `mapNames` which is used when populating submenu // ... } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.fragment_maps, menu); SubMenu mapNamesMenu = menu.findItem(R.id.map_names).getSubMenu(); mapNamesMenu.clear(); for (int i=0; i<mapNames.length; i++) { mapNamesMenu.add(1, i, Menu.NONE, mapNames[i]); } super.onCreateOptionsMenu(menu, inflater); } 

并在res/menu/fragment_maps.xml我有

 <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/map_names" android:title="Maps" android:icon="@drawable/maps_32" android:showAsAction="always|withText"> <menu> <item android:id="@+id/placeholder_maps" /> </menu> </item> </menu> 

一切正常,直到我旋转我的手机。 方向改变后,该菜单变得无法访问(点击图标时没有任何反应)。 然后,如果我再次旋转我的手机,我得到这个错误:

 FATAL EXCEPTION: main android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running? at android.view.ViewRoot.setView(ViewRoot.java:532) at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:177) at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91) at android.view.Window$LocalWindowManager.addView(Window.java:424) at android.widget.PopupWindow.invokePopup(PopupWindow.java:912) at android.widget.PopupWindow.showAsDropDown(PopupWindow.java:824) at com.actionbarsherlock.internal.widget.IcsListPopupWindow.show(IcsListPopupWindow.java:226) at com.actionbarsherlock.internal.view.menu.MenuPopupHelper.tryShow(MenuPopupHelper.java:129) at com.actionbarsherlock.internal.view.menu.MenuPopupHelper.show(MenuPopupHelper.java:102) at com.actionbarsherlock.internal.view.menu.ActionMenuPresenter.onSubMenuSelected(ActionMenuPresenter.java:273) at com.actionbarsherlock.internal.view.menu.MenuBuilder.dispatchSubMenuSelected(MenuBuilder.java:263) at com.actionbarsherlock.internal.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:892) at com.actionbarsherlock.internal.view.menu.ActionMenuView.invokeItem(ActionMenuView.java:510) at com.actionbarsherlock.internal.view.menu.ActionMenuItemView.onClick(ActionMenuItemView.java:145) at android.view.View.performClick(View.java:2494) at android.view.View$PerformClick.run(View.java:9122) at android.os.Handler.handleCallback(Handler.java:587) at android.os.Handler.dispatchMessage(Handler.java:92) at android.os.Looper.loop(Looper.java:130) at android.app.ActivityThread.main(ActivityThread.java:3806) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:507) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597) at dalvik.system.NativeStart.main(Native Method) 

任何想法如何解决? 我正在使用Android 2.3.6

编辑:看testing库

Solutions Collecting From Web of "将项目添加到Fragment中的操作栏选项菜单后,进行方向更改后发生崩溃"

我认为, 这是一个上下文问题 。 这就是发生BadTokenException的原因。

这个例外背后有许多可能性:

1)也许你是使用“ this ”作为上下文引用的地方,它实际上需要YourActivity.this或父活动的上下文。

要么

2)从我猜测的log-cat ,你正试图显示一个Pop-up窗口。

问题可能是,您正在显示popup窗口太早 (即Activity生命周期完成之前)。 所以等到活动生命周期完成。

要延迟显示popup窗口,你可以参考这个链接 。

总之这个问题是由于下面的用例:

一个活动的引用被传递给某个组件(即Toastalert dialogpop-up等),并且活动被销毁,但是这个组件仍然活着,或者试图使用被销毁的活动的上下文。

所以确保没有这样的情况。

希望这会给你一些解决问题的提示。

这是你的MainActivity:

 public class BaseSampleActivity extends SherlockFragmentActivity { TestFragmentAdapter mAdapter; ViewPager mPager; PageIndicator mIndicator; protected ListFragment mFrag; @Override public void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.themed_titles); //This adapter can load as many fragment as you want with different content, see later mAdapter = new TestFragmentAdapter(getSupportFragmentManager()); mPager = (ViewPager)findViewById(R.id.pager); mPager.setAdapter(mAdapter); mPager.setCurrentItem(1); mIndicator = (TitlePageIndicator)findViewById(R.id.indicator); mIndicator.setViewPager(mPager); } @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); //This show how to set up a Searhbar SearchView searchView = new SearchView(getSupportActionBar().getThemedContext()); searchView.setQueryHint("Procure pelo nome"); searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String query) { // TODO Auto-generated method stub // Intent search = new Intent(getApplicationContext(), SearchableActivity.class); // search.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); // search.putExtra("query", query); // startActivity(search); return true; } @Override public boolean onQueryTextChange(String newText) { // TODO Auto-generated method stub return false; } }); menu.add("Search") .setIcon(R.drawable.ic_search_inverse) .setActionView(searchView) .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW); //This is how to set up a SubMenu SubMenu subMenu1 = menu.addSubMenu("Action Item"); subMenu1.add(0, 1, 0, "Sample"); subMenu1.add(0, 2, 0, "Menu"); subMenu1.add(0, 3, 0, "Sair"); MenuItem subMenu1Item = subMenu1.getItem(); subMenu1Item.setIcon(R.drawable.ic_title_share_default); subMenu1Item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { //This is a switch case to do when the SubMenu is clicked. case 1: Toast.makeText(BaseSampleActivity.this, "Now "+item.getItemId(), Toast.LENGTH_SHORT).show(); return true; case 2: Toast.makeText(BaseSampleActivity.this, "Now = "+item.getItemId(), Toast.LENGTH_SHORT).show(); return true; case 3: Toast.makeText(BaseSampleActivity.this, "Now = "+item.getItemId(), Toast.LENGTH_SHORT).show(); return true; } return super.onOptionsItemSelected(item); } } 

这是你的FragmentPagerAdapter:

  class TestFragmentAdapter extends FragmentPagerAdapter implements IconPagerAdapter { //Here you set up the title of each fragment, its in portuguese. protected static final String[] CONTENT = new String[] { "CATEGORIAS", "PRINCIPAL", "AS MELHORES", }; protected static final int[] ICONS = new int[] { R.drawable.perm_group_calendar, R.drawable.perm_group_camera, R.drawable.perm_group_device_alarms, }; private int mCount = CONTENT.length; public TestFragmentAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) {Fragment f = null; switch(position){ case 0: { //Here you can set up a lot of diferent fragment content, here I just created a simple //arraylistfragment f = new ArrayListFragment(); // set arguments here, if required Bundle args = new Bundle(); args.putInt(ArrayListFragment.ARG_position, position); f.setArguments(args); break; } case 1: { f = new ArrayListFragment(); // set arguments here, if required Bundle args = new Bundle(); f.setArguments(args); break; } case 2: { f = new ArrayListFragment(); // set arguments here, if required Bundle args = new Bundle(); f.setArguments(args); break; } default: throw new IllegalArgumentException("not this many fragments: " + position); } return f; } @Override public int getCount() { return mCount; } @Override public CharSequence getPageTitle(int position) { return TestFragmentAdapter.CONTENT[position % CONTENT.length]; } @Override public int getIconResId(int index) { return ICONS[index % ICONS.length]; } public void setCount(int count) { if (count > 0 && count <= 10) { mCount = count; notifyDataSetChanged(); } } } 

我只是做了一个简单的示例,您可以轻松理解如何实现ActionBarSherlock和ViewPagerIndicator。

我想把这个上传到github,但是需要一段时间才能理解如何做,也许你以后可以教我。

然后我在4shared上传这个。 http://www.4shared.com/rar/zOWrvmyu/ViewpagerandSherlock.html

如果您有任何问题,请稍后再问。

这工作对我来说,但我不知道是否有一些副作用。

将此添加到片段的onCreate

 setRetainInstance(true); 

而这个以AndroidManifest.xml来包含Fragment的Activity

 android:configChanges="orientation"