-1

EDIT:: Updated code to show what concerns me: Changing properties of mData in Frag changes properties mData in Sender and their memory reference is the same..

I'm passing a custom data class into a child view via bundles, with the intent of returning data back to the parent. As such, it's convenient that my data object gets passed as a reference, and as such can be manipulated directly.

However, coming from iOS, this is of course against functional programming. I'm mostly just curious here, did I need to do more to implement Serializable? Or is it intended that putSerializable serializes the reference, not the value?

class Sender{

   DataClass mData = new DataClass();
   void openFragment(){
     Bundle bundle = new Bundle();
     bundle.putSerializable("Key", mData);
     Frag frag = new Frag();  //@6945

     //EDIT for test
     {
       testForEquality(bundle);
     }
     frag.setArguments(bundle);
     pushFragment(frag);//Makes a new view appear on top
   }

   void testForEquality(Bundle bundle){
     DataClass newData = (DataClass) bundle.getSerializable("Key");
     Log.e("Equal", "" + (newData == mData); //TRUE
   }
}

class Frag{
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstance){

    DataClass mData = (DataClass) getArguments().getSerializable("Key"); //@6945
    mData.stringA = "Different string value"; //Changes value here AND in Sender
  }
}

class DataClass extends BaseDataClass implements Serializable{
  //Some strings
  //Some ArrayList<Integers>
  //Some enums
  //Some Errors
}
Mars
  • 2,505
  • 17
  • 26
  • I still don't see how this question got downvoted when the only external answer was wrong... – Mars Jul 19 '17 at 05:09

2 Answers2

6

When you serialize an object and pass it to other activity in same application then new copy of Object will be created. This is because the communication with Activities involves IPC, so Bundle will be marshalled into byte[] and in the destination new object will be constructed with the same content.

When you’re putting an Object into Bundle to send to Fragment (as an argument), the objects are held in the internal map of Bundle. Sending arguments to Fragments does not involves any Inter process communication, hence doesn’t need to be marshalling in byte[]. As a result Fragment will get the same object which you sent from the sender Activity. If you modify the object in the Fragment, the object in sender Activity will also changed.

If you want to only pass the values, then Android way to achieve it is to implement Parcelable. You can refer to this SO which describes this approach.

Sagar
  • 23,903
  • 4
  • 62
  • 62
  • +1 for the part about Parcelable! But can you reword the first half? It sounds like a second copy is made, but now when you edit one the Android system (or Java?) edits both. Also, is saying that the reference is passed correct? – Mars May 08 '18 at 08:16
  • Sure. Let me re-phrase it – Sagar May 08 '18 at 08:27
  • Check the udpated answer – Sagar May 08 '18 at 09:13
  • Great lesson. 2 more hours until I can award the bounty, so I'll give it to you later! – Mars May 09 '18 at 00:15
  • So.. if I understand this correctly,. bundle.putSerializable doesn't actually serialize the object then? It just stores the reference to a serializable object? – Mars May 09 '18 at 00:20
  • 1
    Well, you can imply that. Since Serialization is a contract which will be executed when marshalling or unmarshalling is necessary. But there is a case where Serialization with Fragments could yield different objects. The case would be: If Fragment is destroyed and created again due to memory leak or other memory constraints. In this case, marshalling will take place and new Object will be created. – Sagar May 09 '18 at 00:38
  • 1
    Triiiiiiicky :) – Benjamin Piette Feb 26 '19 at 09:17
-2

Implementing the Serializable interface is really enough to make a class serializable. However, changing anything on mData in your fragment won't affect mData in your Sender class, because it's not the reference that is passed.

Headcracker
  • 522
  • 4
  • 19
  • Unless I'm reading something wrong, it IS affecting mData in my Sender class. Sorry for not making that clear. – Mars Jun 23 '17 at 00:14
  • If it is not the reference that is passed, why are Sender.mData and Frag.mData both @6945? – Mars Jun 23 '17 at 00:50
  • Edited the question and code with some additional info to make things more clear – Mars Jun 23 '17 at 00:50
  • I propose an answer below. It explains why the addresses are the same. I still want to test it by writing the serialized data to file, restarting the app and reading in again, but I'll have to do that at a later date – Mars Jun 23 '17 at 05:27