Failure after adding an item to the action bar options menu from a fragment, followed by a change in orientation

I use ActionBarSherlock and ViewPagerIndicator to display fragments as tabs. One of these snippets adds elements to an 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); } 

and in res/menu/fragment_maps.xml I have

 <?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> 

Everything is working fine until I turn my phone. After changing the orientation, this menu becomes unavailable (nothing happens when you click the icon). Then, if I turn my phone again, I get this error:

 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) 

Any ideas how to solve them? I am using Android 2.3.6

Edit: see test repository

+7
source share
3 answers

I think this is a context issue . This is why a BadTokenException occurs.

With this exception, there are many possibilities:

1) Perhaps you are using " this " as a contextual link in some place where she really needs YourActivity.this or the context of parent activity.

OR

2) From log-cat I assume you are trying to display the Pop-up window.

Perhaps the problem is that you are showing the pop-up window too early (i.e. before the Activity life cycle ends). Therefore, wait until the activity life cycle ends.

To delay the display of the popup, you can link to this link.

In a short case, this problem occurs due to the following use case:

The link to the activity is passed to some component (i.e. Toast , alert dialog , Pop-up , etc.), and the activity is destroyed, but this component is still alive or is trying to use the destroyed activity context.

Therefore, make sure that there is no such situation.

Hope this gives you some insight into solving the problem.

+3
source

This is your main activity:

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

This is your 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(); } } } 

I just made a simple example that you can easily understand how to implement ActionBarSherlock and ViewPagerIndicator.

I would like to upload this to github, but it will take some time to figure out how to do this, maybe you can teach me later.

Then I upload it to 4shared. http://www.4shared.com/rar/zOWrvmyu/ViewpagerandSherlock.html

If you have any questions, ask me later.

+2
source

It worked for me, but I don’t know if there are any side effects.

Add this to the onCreate Snippet

 setRetainInstance(true); 

and this is for AndroidManifest.xml for an Activity containing a fragment

 android:configChanges="orientation" 
+1
source

All Articles