1

I'm working with ActionBarSherlock, I need to change some icons on the action bar when the user does some stuff. In order to that I have to save the action bar for later usage :

private Menu actionBarMenu;

...

@Override
public boolean onCreateOptionsMenu(Menu menu)
{
    MenuInflater inflater = getSupportMenuInflater();
    inflater.inflate(R.menu.map_activity_menu, menu);
    actionBarMenu = menu;
    return super.onCreateOptionsMenu(menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item)
{
    actionBarMenu.findItem(R.id.follow_my_position).setIcon(R.drawable.toolbar_myposition_active);
}

Okay ! Here's where the problems begin. When I rotate the screen, I get a NullPointerException on actionBarMenu.
I know... I didn't save it before the screen was rotated, so normally I would go to onSaveInstanceState and save my Menu there, except the actionBarMenu is an interface... More specifically, the interface com.actionbarsherlock.view.Menu and I can't modify it so that it implements Parcelable or Serializable.

So how can I save an interface in the bundle ?

Mehdiway
  • 10,337
  • 8
  • 36
  • 68

4 Answers4

1

You should not keep reference to your action bar during configuration changes. After screen rotate, Android will recreate your activity and all UI references should be released, otherwise you will introduce reference leak.

Why dont you get your actionBarMenu reference again inside boolean onCreateOptionsMenu, after activity rotates?

marcinj
  • 48,511
  • 9
  • 79
  • 100
0

You don't. You don't save the interface. You save some String, or boolean, or integer, representing the action the user did. Then you check this value and change the menu again.

Budius
  • 39,391
  • 16
  • 102
  • 144
0

You can't. However, you can still retain your member variable on an orientation change by adding the following code to your activity

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Object last = getLastNonConfigurationInstance();
    if (last != null && last instanceof Menu) {
        actionBarMenu = (Menu) last;
    }
}

// for FragmentActivity it is onRetainCustomNonConfigurationInstance
public Object onRetainNonConfigurationInstance() {
    return actionBarMenu;
};
Mehdiway
  • 10,337
  • 8
  • 36
  • 68
Thrakbad
  • 2,728
  • 3
  • 23
  • 31
  • 1
    Wont this be a reference to the menu from the previous Activity and not the menu in the re-created (current) one? – Kuffs Jan 23 '14 at 16:11
  • Oh yes it will be. I didn't read the question exactly and thought you are trying to retain any custom class that dowsn't depend on your `Activity`. My bad. – Thrakbad Jan 23 '14 at 16:13
  • Couldn't find any method called `onRetainCustomNonConfigurationInstance()` but I found `onRetainNonConfigurationInstance()` and it worked just fine. Thanks :) – Mehdiway Jan 23 '14 at 16:20
  • Oh well, I just convinced myself that it did not work and changed my answer. But now I'll change it back to the original ;-) – Thrakbad Jan 23 '14 at 16:22
0

Does this work before the rotate? Because a rotation just recreates the entire activity - i.e. it goes through the whole creation process again. So, I'm not sure that the recreation is your problem, because onCreateOptionsMenu(Menu menu); should be called again, anyway.

Are you sure that your actionBarMenu.findItem(R.id.follow_my_position) is returning correctly? Instead of handling it how your currently are - why not just...not store the menu and check the clicked menu item instead?

For example:

@Override
public boolean onOptionsItemSelected(MenuItem item)
{
     switch(item.getItemId()){
         case R.id.follow_my_position:
             item.setIcon(R.drawable.toolbar_myposition_active);
     }
}

or if that's not what you're looking for, check that your findItem() call finds the item:

MenuItem item = actionBarMenu.findItem(R.id.follow_my_position);
if(item != null){
    item.setIcon(R.drawable.toolbar_myposition_active);
}
Submersed
  • 8,810
  • 2
  • 30
  • 38