Search code examples
androidserializable

Saving object reference in onSaveInstanceState using Serializable?


I need clarification on how I can save the state of an object that has a reference to another object?

Lets say I have the below class objects that I need to save and restore:

public class ObjectA implements Serializable{
    private List<ObjectB> mObjectBList;
}

public clas ObjectB implements Serializable {
    // some other members here
    private ObjectA mParent;
}

Here are the code to invoke the save and restore in a fragment:

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putSerializable("ObjectA", mObjectA);
}

@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    if (savedInstanceState != null) {
        mObjectA = (mObjectA) savedInstanceState.getSerializable("ObjectA");
    }
}

Questions:

  1. Will saving mObjectA also save every object in mObjectBList?
  2. Since mObjectB has a reference to its parent ObjectA, will ObjectA be re-instantiated for each ObjectB? Which then in turn will re-instantiate ObjectB, and then it will re-instantiate ObjectA, and so forth, leading to an infinite loop?
  3. How would you solve this problem?

I'm not clear on what happens when an object gets saved as a Serializable, so please help me understand how Android distinguishes when to instantiate a new object and when it will reproduce an actual reference.


Solution

    1. Yes. But List is not Serializable. Change List to ArrayList for example.

    2. It works fine. Java serialization works for cyclic references. Here is similar question.

    3. I think there is no problem.

    I did test with following code.

    public class MainActivity extends AppCompatActivity {
    
        private ObjectA mObjectA;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            if (savedInstanceState != null) {
                mObjectA = (ObjectA) savedInstanceState.getSerializable("ObjectA");
                // check mObjectA == mObjectA.getObjectBList().get(0).getParent();
    
            } else {
                mObjectA = new ObjectA();
                ArrayList<ObjectB> list = new ArrayList<>();
                list.add(createB());
                list.add(createB());
                list.add(createB());
                list.add(createB());
                list.add(createB());
                mObjectA.setObjectBList(list);
            }
        }
    
        private ObjectB createB() {
            ObjectB objectB = new ObjectB();
            objectB.setParent(mObjectA);
            return objectB;
        }
    
        @Override
        public void onSaveInstanceState(Bundle outState) {
            super.onSaveInstanceState(outState);
            outState.putSerializable("ObjectA", mObjectA);
        }
    }
    
    public class ObjectA implements Serializable {
        private ArrayList<ObjectB> mObjectBList;
    
        public void setObjectBList(ArrayList<ObjectB> objectBList) {
            mObjectBList = objectBList;
        }
    
        public ArrayList<ObjectB> getObjectBList() {
            return mObjectBList;
        }
    }
    
    public class ObjectB implements Serializable {
        // some other members here
        private ObjectA mParent;
    
        public void setParent(ObjectA parent) {
            mParent = parent;
        }
    
        public ObjectA getParent() {
            return mParent;
        }
    }