java - 为什么即使我没有实现必要的功能,Parcelable 也能工作?

标签 java android fragment parcelable screen-rotation

我想在屏幕旋转期间保留一个复杂的 java 对象,所以我将对象设为 Parcelable 并实现了必要的方法:

  1. 在 writeToParcel(Parcel dest, int flags) 方法中,我将一些值保存到“dest”。
  2. 在 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");
}

这非常有效。

然后我做了如下测试:

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

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

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

最佳答案

是的,所以这与 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()——您可以通过断言配置更改前后的对象具有相同的 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 <application_id> 来强制执行此操作)然后恢复,然后您将遇到数据不存在的问题正确包装。

关于java - 为什么即使我没有实现必要的功能,Parcelable 也能工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34816929/

相关文章:

java - 你能调用带有链接的 servlet 吗?

java - 如何通过电子邮件将文本文件作为附件发送 - Android?

带有滑动选项卡的 Android 操作栏

android - OnvideoClicklistener 问题转到 YouTube 主页

java - Android:插入 fragment 时出错

Java 递归和归并排序

java - 是否可以让 MediaPlayer 播放一个音频文件并在播放完后播放下一个?

android - 覆盖完成 Activity 的动画

android - 从 Activity android调用时不想刷新tabsactivity

java - 在 Fragment 中设置 onBackPressed