44

I created an instance of a custom class RestaurantList to hold my data (a list of restaurant data received from a web service as json data).

How can I save it in onSaveInstanceState?

Macarse
  • 91,829
  • 44
  • 175
  • 230
jul
  • 36,404
  • 64
  • 191
  • 318

6 Answers6

62

Custom objects can be saved inside a Bundle when they implement the interface Parcelable. Then they can be saved via:

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putParcelable("key", myObject);
    }

Basically the following methods must be implemented in the class file:

 public class MyParcelable implements Parcelable {
     private int mData;

     public int describeContents() {
         return 0;
     }

     /** save object in parcel */
     public void writeToParcel(Parcel out, int flags) {
         out.writeInt(mData);
     }

     public static final Parcelable.Creator<MyParcelable> CREATOR
             = new Parcelable.Creator<MyParcelable>() {
         public MyParcelable createFromParcel(Parcel in) {
             return new MyParcelable(in);
         }

         public MyParcelable[] newArray(int size) {
             return new MyParcelable[size];
         }
     };

     /** recreate object from parcel */
     private MyParcelable(Parcel in) {
         mData = in.readInt();
     }
 }
Maaalte
  • 6,011
  • 3
  • 29
  • 27
  • 6
    I find it to be less work to translate into and back from JSON, compared to parcelable – Arcantos Aug 04 '16 at 22:06
  • 2
    onSaveInstanceState should be at the end of the function! https://developer.android.com/training/basics/activity-lifecycle/recreating.html – Denny Weinberg Sep 28 '16 at 20:08
  • While this is the right way to save the custom object in onSaveInstanceState() you should ensure that you do not save big objects using this method. This is just to save the state of the screen. If objects becomes large, there is a chance that you get `TransactionTooLargeException` exception – abat Apr 27 '17 at 10:07
  • @abat can you define "large"? – Mitch May 01 '19 at 17:28
  • onSaveInstanceState is documented in examples at the end of the function. It appears it works either way. – Mitch May 01 '19 at 17:54
  • @Mitch 1MB is the limit. Now with ViewModel and liveData, most of the things can be saved using that pattern – abat May 21 '19 at 20:41
3

I know "that this case is cold", but because i found this thread first, when I was searching for exactly the same thing (and found an answer by now):

Imagine Bundle as an XML file. If you create a new <BUNDLE name="InstanceName" type="ClassName"> you can freely add elements and attributes in a fresh and empty namespace.

When onSaveInstance(Bundle outState) of your MainActivity is called (you can also force this in onPause), you can create a new: Bundle b = new Bundle();

Then call your (probably not inherited and not overriden) custom Method onSaveInstance(Bundle b) in your own class with your newly created Bundle b. Then (in onSaveInstance(Bundle outState)) of your MainActivity, call outState.putBundle("StringClassAndInstanceName", b);

When you find this string in onCreate, you can either use a switch/case to recreate this object or (better) have a factory function in your custom class to work with Bundle and "StringClassAndInstanceName".

dsewtz
  • 31
  • 2
3

Kotlin Solution: For custom class save in onSaveInstanceState you can be converted your class to JSON string and restore it with Gson convertion. The following example is for Fragment and Activity:

For Activity:

For put class in saveInstanceState:

override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        val gson = Gson()
        val json = gson.toJson(your_custom_class)
        outState.putString("CUSTOM_CLASS", json)
    }

Restore class:

 override fun onRestoreInstanceState(savedInstanceState: Bundle) {
    super.onRestoreInstanceState(savedInstanceState)
    val json = savedInstanceState?.getString("CUSTOM_CLASS")
    if (!json!!.isEmpty()) {
        val gson = Gson()
        testBundle = gson.fromJson(json, Session::class.java)
    }
 }

You can restore it on Activity onCreate also.

For fragment:

For put class in saveInstanceState:

 override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        val gson = Gson()
        val json = gson.toJson(customClass)
        outState.putString("CUSTOM_CLASS", json)
    }

Restore class:

 override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        if (savedInstanceState != null) {
            val json = savedInstanceState.getString("CUSTOM_CLASS")
            if (!json!!.isEmpty()) {
                val gson = Gson()
                val customClass: CustomClass = gson.fromJson(json, CustomClass::class.java)
            }
        }
    }
Jamil Hasnine Tamim
  • 4,389
  • 27
  • 43
2

Custom objects can be saved inside a Bundle when they implement the interface Serializable

Then they can be saved via:

override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        outState.putSerializable("key", myObject)
}

Suppose myObject is object of class CustomClass and CustomClass implement the interface Serializable

Since the expected value in outState.putSerializable will be of type Serializable, you can pass myObject (you can send object of child class where parent class object is expected)

Then they can be used via:

override fun onCreate(savedInstanceState: Bundle?) {
    if (savedInstanceState != null) {
        myObject = savedInstanceState.getSerializable("key") as CustomClass
    }
}
  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/31952402) – nvidot Jun 12 '22 at 14:26
1

Check this answer.

Basically you have to save it inside a Bundle.

Community
  • 1
  • 1
Macarse
  • 91,829
  • 44
  • 175
  • 230
  • Ok thanks, maybe I wasn't clear enough. What I wanted to know is how to save a *custom* object. I found that I can make it parcelable. – jul Jul 04 '10 at 10:57
1

Custom class objects can be converted to JSON and stored in the bundle as a string. The following example is for Fragments.

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    Gson gson = new Gson();
    String json= gson.toJson(customClass);
    outState.putString("CUSTOM_CLASS", json);
}

public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    if(savedInstanceState != null) {
        String json= savedInstanceState.getString("CUSTOM_CLASS");
        if(!json.isEmpty()) {
        Gson gson = new Gson();
            CustomClass customClass = gson.fromJson(json, CustomClass.class);
        }
    }
}

For Activities, override onRestoreInstanceState method instead.

Andrew Lee
  • 446
  • 4
  • 7