views:

67

answers:

2

Hello, I was looking at the way Android handles orientation change for my application (I discovered that it restarts the mainactivity on orientation change :| ). I've seen that you can ovveride the method

protected void onSaveInstanceState(Bundle outState)

to save stuff, then have the in onStart. The problem is that I've my view with custom objects and a listview using a custom adapter... Everything is in a ArrayList of these objects, but I've noticed that you can't put arbitrary objects in the bundle! So how do I save the state?

+2  A: 

If you want to retain your own (non view-state) data, you can actually pass an arbitrary object specifically for orientation changes using onRetainNonConfigurationInstance(). See this Android Developers blog post. Just be careful not to put any Views or other references to the pre-rotation Context/Activity in the object you pass, or you'll prevent those objects from being garbage collected and may eventually run out of memory (this is called a context leak).

Yoni Samlan
Note that onRetainNonConfigurationInstance() should *only* be used as an optimization. Your app should still work even if this doesn't happen... because there is *no* guarantee that it will, and in fact many situations where it definitely won't be called. You should first make your app work correctly through the full saved state mechanism, and only implement this method as an optimization.
hackbod
+1  A: 

First, you need to determine what is actually the "state" in your app. You haven't said what you are actually doing, but let me assume that the ArrayList of objects is the state the user is working with.

Second, decide what the lifecycle of this state actually is. Is it really tied to that activity? Or should the user not lose it if say their battery runs low, the device turns off, and they later return to your app? If the former, onSaveInstanceState() is correct; if the latter, you'll want to save to persistent storage in onPause().

For onSaveInstanceState() with custom objects, the key is to implement the Parcelable interface. This involves implementing the methods on Parcelable, as well as making a static CREATOR object in your class. Here's the code for a typical simple Parcelable class:

http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;f=core/java/android/content/ComponentName.java

The key functions are the Parcelable implementation:

http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;f=core/java/android/content/ComponentName.java;h=7ca0f01b986924d939b57061966ec8526de9e608;hb=HEAD#l214

and the CREATOR static class:

http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;f=core/java/android/content/ComponentName.java;h=7ca0f01b986924d939b57061966ec8526de9e608;hb=HEAD#l256

(The static writeToParcel() and readFromParcel() are just conveniences that were done for that class and not required.)

Now that you have that, you can put your entire ArrayList of objects into the saved state Bundle with Bundle.putParcelableArrayList:

http://developer.android.com/reference/android/os/Bundle.html#putParcelableArrayList(java.lang.String, java.util.ArrayList)

In Activity.onCreate(), check to see if you have a savedState Bundle, and if so try to retrieve the ArrayList from that and use it if found, creating a new adapter and list view for the new activity that are used to display it.

hackbod