Bundle.putSerializable 序列化引用,不是值?
Bundle.putSerializable serializing reference, not value?
编辑::更新代码以显示我关心的问题:更改 Frag 中 mData 的属性会更改 Sender 中的 mData 属性,并且它们的内存引用相同..
我正在通过捆绑将自定义数据 class 传递到子视图,目的是将数据返回给父视图。因此,我的数据对象作为引用传递很方便,因此可以直接操作。
但是,来自 iOS,这当然是反对函数式编程的。我主要只是好奇,我是否需要做更多的工作来实现可序列化?还是 putSerializable 序列化引用而不是值?
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
}
实现 Serializable 接口确实足以使 class 可序列化。但是,更改片段中 mData 的任何内容都不会影响 Sender class 中的 mData,因为传递的不是引用。
当您序列化一个对象并将其传递给同一应用程序中的其他 activity 时,将创建对象的新副本。这是因为与Activity的通信涉及到IPC,所以Bundle会被编组成byte[],在destination中会构造出相同内容的新对象。
当您将一个对象放入 Bundle 以发送给 Fragment(作为参数)时,这些对象保存在 Bundle 的内部映射中。向片段发送参数不涉及任何进程间通信,因此不需要在 byte[] 中编组。结果,Fragment
将获得与您从发件人 Activity 发送的 相同的对象 。如果修改Fragment中的对象,sender中的对象Activity也会改变。
如果你只想传递值,那么 Android 实现它的方法是实现 Parcelable
。您可以参考描述此方法的SO。
编辑::更新代码以显示我关心的问题:更改 Frag 中 mData 的属性会更改 Sender 中的 mData 属性,并且它们的内存引用相同..
我正在通过捆绑将自定义数据 class 传递到子视图,目的是将数据返回给父视图。因此,我的数据对象作为引用传递很方便,因此可以直接操作。
但是,来自 iOS,这当然是反对函数式编程的。我主要只是好奇,我是否需要做更多的工作来实现可序列化?还是 putSerializable 序列化引用而不是值?
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
}
实现 Serializable 接口确实足以使 class 可序列化。但是,更改片段中 mData 的任何内容都不会影响 Sender class 中的 mData,因为传递的不是引用。
当您序列化一个对象并将其传递给同一应用程序中的其他 activity 时,将创建对象的新副本。这是因为与Activity的通信涉及到IPC,所以Bundle会被编组成byte[],在destination中会构造出相同内容的新对象。
当您将一个对象放入 Bundle 以发送给 Fragment(作为参数)时,这些对象保存在 Bundle 的内部映射中。向片段发送参数不涉及任何进程间通信,因此不需要在 byte[] 中编组。结果,Fragment
将获得与您从发件人 Activity 发送的 相同的对象 。如果修改Fragment中的对象,sender中的对象Activity也会改变。
如果你只想传递值,那么 Android 实现它的方法是实现 Parcelable
。您可以参考描述此方法的SO。