为啥 Parcelable 工作,即使我没有实现必要的功能?

Posted

技术标签:

【中文标题】为啥 Parcelable 工作,即使我没有实现必要的功能?【英文标题】:Why does Parcelable work even though I did not implement the necessary functions?为什么 Parcelable 工作,即使我没有实现必要的功能? 【发布时间】:2016-04-21 09:25:46 【问题描述】:

我想在屏幕旋转过程中保留一个复杂的java对象,所以我把对象做成Parcelable并实现了必要的方法:

    在 writeToParcel(Parcel dest, int flags) 方法中,我将一些值保存到“dest”。 在 Parcelable.Creator 的 createFromParcel(Parcel source) 方法中,我以正确的顺序从“源”中获取值并返回相应的对象。

然后在 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");

效果很好。

然后我做了以下测试:

    在 writeToParcel 方法中删除了我所有的代码。 在 createFramParcel 方法中返回 null。

当我运行应用程序时,我得到了完全相同的结果!我得到了一个包含所有适当值的对象。

为什么会这样? Parcelable 是否“自动”创建 Parcelable 对象?

【问题讨论】:

我很确定,onSaveInstanceState() 中的调用顺序是错误的(保存后您正在修改捆绑包)。 【参考方案1】:

是的,所以这与 Bundle 在内部处理缓存和打包的方式有关。当您调用putParcelable() 时,它会运行以下代码:

public void putParcelable(@Nullable String key, @Nullable Parcelable value) 
    unparcel();
    mMap.put(key, value);
    mFdsKnown = false;

所以基本上,Bundle 中的数据不会立即写入Parcel——mMapArrayMap<String, Object>,它包含Bundle 中所有对象的缓存,因为它们被插入或删除。

在某些时候,writeToParcel() 将在 Bundle 上调用,此时 mMap 中的所有内容都会写入 mParcelledData

所以基本上,当您进行配置更改时,Bundle 仍然没有写入Parcel,因此您传入的对象的相同实例仍存储在Bundle 的@ 中987654335@(因此您的对象也从未调用过writeToParcel() - 您可以通过断言配置更改前后的对象具有相同的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 对象写入保存状态包,并将您的应用程序置于后台直到进程终止(或者我相信您可以通过运行 adb shell am kill &lt;application_id&gt; 强制执行该操作)然后恢复,您'然后会遇到数据未正确打包的问题。

【讨论】:

以上是关于为啥 Parcelable 工作,即使我没有实现必要的功能?的主要内容,如果未能解决你的问题,请参考以下文章

未解决的参考:Parcelable Kotlin

当意图传递给其他活动时,为啥从 parcelable 中得到错误的值?

为啥我的 python 脚本没有显示为进程,即使它正在运行?

Android 中的 Parcelable 和继承

为啥即使没有 SVN 更改,Jenkins 也会触发 IVY 构建?

X 类不是抽象的,没有实现 android.os.Parcelable 中定义的 fun writeToParcel()