我想在屏幕旋转期间保留复杂的java对象,所以我使对象Parcelable并实现了必要的方法:
然后在Fragment的onSaveInstanceState中我保存了Parcelable:
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable("myObject", myObject);
}
并将我的对象放入Fragment' onCreate:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyObject myObject = savedInstanceState.getParcelable("myObject");
}
这完美无缺。
然后我做了一个测试:
当我运行应用程序时,我得到了完全相同的结果!我得到了一个包含所有适当值的对象。
为什么会这样? Parcelable是否可以创建" Parcelable对象"自动?
答案 0 :(得分:7)
是的,所以这与Bundle在内部处理缓存和分区的方式有关。当您致电putParcelable()
时,它会运行以下代码:
public void putParcelable(@Nullable String key, @Nullable Parcelable value) {
unparcel();
mMap.put(key, value);
mFdsKnown = false;
}
基本上,Bundle
中的数据不会立即写入Parcel
- mMap
是ArrayMap<String, Object>
,它包含所有对象的缓存Bundle
,因为他们已插入或删除。
在某些时候,writeToParcel()
会调用Bundle
,此时mMap
中的所有内容都会被写入mParcelledData
。
所以基本上,当你进行配置更改时,Bundle
仍然没有被写入Parcel
,所以你传入的对象的同一个实例仍然存储在Bundle
mMap
(因此您的对象也从未调用writeToParcel()
- 您可以通过断言配置更改前后的对象具有相同的{{}来确认这一点1}})。
您可以在System.identityHashCode()
:
BaseBundle
因此,如果您要将// Invariant - exactly one of mMap / mParcelledData will be null
// (except inside a call to unparcel)
ArrayMap<String, Object> mMap = null;
/*
* If mParcelledData is non-null, then mMap will be null and the
* data are stored as a Parcel containing a Bundle. When the data
* are unparcelled, mParcelledData willbe set to null.
*/
Parcel mParcelledData = null;
对象写入保存状态包,并将应用程序置于后台,直到进程终止(或者我相信您可以通过运行Parcelable
强制执行此操作)然后恢复,然后您将遇到数据未正确分配的问题。