[英]Why does Parcelable work even though I did not implement the necessary functions?
I wanted to retain a complex java object during screen rotation, so I made the object Parcelable and implemented necessary methods:我想在屏幕旋转期间保留一个复杂的 java 对象,所以我制作了对象 Parcelable 并实现了必要的方法:
Then in Fragment's onSaveInstanceState I saved the Parcelable:然后在 Fragment 的 onSaveInstanceState 中我保存了 Parcelable:
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable("myObject", myObject);
}
and got my object in Fragment's onCreate:并在 Fragment 的 onCreate 中获取我的对象:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyObject myObject = savedInstanceState.getParcelable("myObject");
}
This worked Perfectly.这非常有效。
Then I made the following test:然后我做了以下测试:
When I ran the app I got THE EXACT SAME RESULT.当我运行该应用程序时,我得到了完全相同的结果。 I got an object with all the appropriate values in it.
我得到了一个包含所有适当值的对象。
Why did this work?为什么这样做? Does Parcelable create Parcelable objects "automatically"?
Parcelable 是否“自动”创建 Parcelable 对象?
Yeah, so this has to do with the way Bundle handles caching and parceling internally.是的,所以这与 Bundle 在内部处理缓存和打包的方式有关。 When you call
putParcelable()
, it runs the following code:当您调用
putParcelable()
时,它会运行以下代码:
public void putParcelable(@Nullable String key, @Nullable Parcelable value) {
unparcel();
mMap.put(key, value);
mFdsKnown = false;
}
So basically, data in a Bundle
is not immediately written to a Parcel
-- mMap
is an ArrayMap<String, Object>
and it contains a cache of all the objects in the Bundle
as they're inserted or removed.所以基本上,
Bundle
中的数据不会立即写入Parcel
—— mMap
是一个ArrayMap<String, Object>
并且它包含Bundle
中插入或删除的所有对象的缓存。
At some point, writeToParcel()
will be called on the Bundle
, at which point everything in mMap
gets written into mParcelledData
.在某个时候,将在
Bundle
上调用writeToParcel()
,此时mMap
中的所有内容都将写入mParcelledData
中。
So basically, when you do a config change, the Bundle
still hasn't been written to a Parcel
, so the same instance of the object you passed in is still stored in the Bundle
's mMap
(so your Object also has never had writeToParcel()
invoked -- you can confirm this by asserting that the object before and after config change have the same System.identityHashCode()
).所以基本上,当您进行配置更改时,
Bundle
仍未写入Parcel
,因此您传入的对象的相同实例仍存储在Bundle
的mMap
(因此您的 Object 也从未有过writeToParcel()
调用——您可以通过断言配置更改前后的对象具有相同的System.identityHashCode()
来确认这一点。
You can see notes about this in BaseBundle
:你可以在
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;
So if you were to write your Parcelable
object to the save state bundle, and put your app in the background until the process dies (or I believe you can force that by running adb shell am kill <application_id>
) and then resume, you'll then run into the problem where your data isn't parceled correctly.因此,如果您要将
Parcelable
对象写入保存状态包,并将您的应用程序置于后台直到进程结束(或者我相信您可以通过运行adb shell am kill <application_id>
强制执行此操作)然后恢复,您然后,您会遇到数据未正确打包的问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.