我正在处理Android项目,我想将自定义类MainActivityModel
传递给Fragment
,MainActivityPlaceholderFragment
。
我已将MainActivityModel
序列化:
public class MainActivityModel implements Serializable{
public int current = 0;
public int pageCount = 0;
public boolean pristine = true;
// Stores the fetched dataMap
public ArrayList<HashMap<String, String>> arrayList;
public MainActivityModel() {
this.arrayList = new ArrayList<>();
}
public String getCategory() {
return Util.categories[current];
}
public CharSequence getmTitle () {
return Util.toTitleCase(
Util.mapCategoryPretty(Util.categories[current]));
}
}
我将它传递给Fragment
,就像这样:
public static MainActivityPlaceholderFragment newInstance(MainActivityModel mainActivityModel) {
MainActivityPlaceholderFragment fragment = new MainActivityPlaceholderFragment();
Bundle args = new Bundle();
args.putSerializable(ARG_DATA_MODEL, mainActivityModel);
fragment.setArguments(args);
Log.v(LOG_TAG, "Created: " + mainActivityModel.getmTitle());
return fragment;
}
我这样访问:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mainActivityModel = (MainActivityModel) getArguments().getSerializable(ARG_DATA_MODEL);
mMainActivityPlaceholderFragmentView = new MainActivityPlaceholderFragmentView(this, mainActivityModel);
mCallbacks.onPlaceholderFragmentCreated(mainActivityModel.current);
}
我最初认为(在阅读下面提到的答案之后),序列化将数据转换为字节并在需要时随后恢复它们。所以我的对象将被复制。如果我只想访问数据,这是可以的。但我也想从片段中修改实际模型(在MainActivity
中引用)。
要进行实验,我在片段中将pristine
设置为false
,并将其记录在MainActivity
中,这确实是错误的。
但如果序列化是按值传递的,那么这是怎么回事?
我读过的内容:
答案 0 :(得分:3)
对Serializable
对象的引用仍然是对象引用,它与传递List
对象或Foo
对象没有什么不同。令人困惑的部分是 if 和 序列化发生。
来自android.app.Fragment.setArguments(Bundle)
的文档:
此处提供的参数将在片段销毁和创建中保留。
有两种方法可以实现这一目标:
Bundle
仅存储原始字节,并为每个get
/ put
操作序列化/反序列化。Bundle
保存活动对象,并要求它在需要销毁/重新创建片段时序列化/反序列化所有内容。显然,第一个选项非常效率低下:get
/ put
操作比活动/片段生命周期更改频繁得多。因此,Android只会在生命周期更改时序列化/反序列化 。
这会导致您的用例中出现“怪异”行为。您假设Serializable
对象已由Bundle
立即序列化 ,而Bundle
只是保留对您的对象的引用。由于片段未在newInstance
和onCreate
调用之间被销毁,因此您看到完全相同的Bundle
包含完全相同的引用。
当然,您应该不依赖对这些引用保持不变。每当您的应用程序被要求保持其状态时(例如,当转到后台,旋转屏幕时,或系统需要释放RAM时),这些对象将被序列化并且引用已经消失。将从序列化数据重新创建对象,但它们将具有不同的引用。
答案 1 :(得分:0)
在Java中,所有对象都通过引用传递,只有基本类型(int,float,long ...)按值传递。
我真的不知道Serializable是如何工作的,但是如果它转换为不是基本类型的byte []那么这就是它工作的原因。
如果你将一个Serializable类写入一个文件并将其打开为ASCII,你会看到一种递归的toString(),然后可能是数据作为字节。
希望这有帮助。
答案 2 :(得分:0)
序列化会创建对象的深层副本,这意味着如果序列化然后反序列化包含其他对象的对象,您将获得新的独立对象(带有新引用),所有内容的副本,绝对不会引用您仍然拥有的对象在堆上。因此,如果修改刚刚反序列化的对象,则只能修改这些对象,而不能修改堆上可能存在的任何引用。
如果你想重新调整你刚刚用内存中的对象反序列化的引用,你必须对它进行编码。
答案 3 :(得分:0)
您描述的行为看起来很像Parcel active objects,而不是sun-java风格的序列化。