Tuesday, March 12, 2013

Easier View State Saving

If you write your own custom Views you may eventually want to leverage onSaveInstanceState() and onRestoreInstanceState() to store some data relating to the View.  Unlike Activity/Fragment, which use Bundle to pass around the instance state, Views use Parcelables for their instance state.

Parcelable is fast, efficient, and kind of a pain in the ass to setup.  It's doubly painful for custom Views as you have to ensure that you're properly saving the superclass' state as well in your own Parcelable.  The boilerplate code is excessive.

It turns out there's a much easier way which leverages these two points:

  1. Bundles implement Parcelable.  This means you can use a Bundle instead of a custom Parcelable as your instance state.
  2. Bundles can store Parcelables.  This means you can preserve the superclass' state in your Bundle.

Here's a simple implementation of the concept:
public class CustomView extends View {
  public CustomView(Context context) {
    super(context);
  }

  @Override
  protected Parcelable onSaveInstanceState() {
    Bundle bundle = new Bundle();
    bundle.putParcelable("superState", super.onSaveInstanceState());
    // Put whatever you want into the Bundle here
    return bundle;
  }

  @Override
  protected void onRestoreInstanceState(Parcelable state) {
    Bundle bundle = (Bundle) state;
    super.onRestoreInstanceState(bundle.getParcelable("superState"));
    // Restore what you put into the bundle here
  }
}

At this point you can store any primitives in a Bundle as you normally would in an Activity/Fragment.  Plus, if you use this trick many times you could even wrap it in a subclass of View (and simply replace the default instance state with a Bundle version of it).

No comments:

Post a Comment