Android:Parcelable.writeToParcel和Parcelable.Creator.createFromParcel从未被调用

24

我完全是新手,在这里发布问题,但我已经在这里阅读了很多年。通常情况下,通过彻底搜索网络,我总能找到答案,但这一次我不知所措...

在又度过了一天试图弄清楚为什么它不能工作后,我决定寻求帮助,希望你们能给我一些指针,或者更好的解决方案。

问题: 在一个Android游戏中,当用户按HOME键等操作时,我必须让应用程序记住其状态。经过一些搜索,我意识到为了使我的类在重新打开应用程序后能够初始化回到其适当的状态,我必须支持Parcelable接口以通过Bundle传递它们。

在我的onStop和onStart函数中,我分别将游戏状态保存到和从Bundle中恢复,但是当我在Bundle上调用putParcelable和getParcelable函数时,对象的writeToParcel和createFromParcel函数从未被调用。

担心这可能是由于游戏相对复杂导致的,我想最好创建一个非常简单的应用程序来尝试使它工作。

基于我在网上看到的许多Parcelable示例,这成为了我的类:

public class ParcelableTest implements Parcelable {
  int id;

  public ParcelableTest(int newID)
  {
    id = newID;
  }

  private ParcelableTest(Parcel in) {
      readFromParcel(in);
  }

  public void writeToParcel(Parcel out, int arg1) {
      writeToParcel(out);
  }

  public void writeToParcel(Parcel out) {
    Log.v("ParcelableTest","Writing to parcel");
      out.writeInt(id);
  }

  public void readFromParcel(Parcel in) {
      id = in.readInt();
  }

  public int describeContents() {
      return 0;
  }

  public static final Parcelable.Creator<ParcelableTest> CREATOR = new
  Parcelable.Creator<ParcelableTest>() {
      public ParcelableTest createFromParcel(Parcel in) {
          Log.v("ParcelableTest","Creating from parcel");
              return new ParcelableTest(in);
      }

      public ParcelableTest[] newArray(int size) {
              return new ParcelableTest[size];
      }
  };
}

从我的主活动中,我将调用以下函数来保存/还原数据:

public Bundle saveToBundle(Bundle savedState)
    {
      savedState.putParcelable("Test1",mTest1);
      savedState.putParcelable("Test2",mTest2);
      return savedState;
    }
    public void restoreFromBundle(Bundle savedState)
    {
      mTest1 = savedState.getParcelable("Test1");
      mTest2 = savedState.getParcelable("Test2");

    }

但是出于某种原因,我的测试类中的putParcelable和getParcelable函数都无法导致适当的Parcelable调用。

最奇怪的是它确实以某种方式读取了正确的值(我已经尝试使用类中的更多变量),但我的调试和日志显示应用程序从未到达writeToParcel和createFromParcel。

我在这里缺少什么?

任何帮助/想法将不胜感激。


如果这个答案解决了你的问题,你能标记一下吗?或者你找到了更好的解决方案吗?你可以在这里发布吗? - superjos
3个回答

12
显然,Android Bundle类不遵循IPC封送协议,而是采用反射将Parcelable对象写入和读取到其自己的内部映射中。根据我们进行的测试,似乎Bundle会写入/读取您声明的Parcelable派生类中定义的每个字段,只因为您声明了这些字段。请注意保留"{{"和"}}"以及html标签。

2
除了活动被销毁时调用Parcelable方法的情况外,这似乎是正确的。 - mmm111mmm
同样的问题。即使将变量标记为瞬态,也无济于事。它仍然会被序列化。这是引入恶性错误的意外行为。你们中有人开了一个关于这个问题的票吗? - MaiOM
不,我们没有。回头看,可能我们认为这是与实现细节过于接近,而不是Bundle应该发挥作用的目的。基本上我同意@Luis所写的内容。 - superjos
这个有文档记录吗? - dldnh
那时候(3年前),我们找不到任何相关信息。我们是通过“艰难的方式”学习的。另外,关于文档,请看@Luis的回答。 - superjos
1
@newfivefour是正确的。如果你需要在你的parcelable方法中调试一些东西,你可以进入开发者选项并勾选“不保留活动”。 - yuval

4

从技术上讲,文档并没有说writeToParcelcreateFromParcelonSaveInstance 中被调用。事实上,如果您在代码中检查savedState,您会发现在保存和还原情况下它是完全相同的对象实例;如果可以避免序列化-反序列化就很有意义。
另一方面,文档也没有说不进行序列化。结论应该是你不应该依赖于任何一种情况,只需假设您获得了正确的bundle。

此外,您可能想要查看http://developer.android.com/guide/topics/resources/runtime-changes.html


0

我确认superjos所说的。

在saveToBundle事件中,Android bundle只是通过反射存储类的成员,并不调用Parcelable函数。

我为这个问题浪费了一整天!太遗憾了....

这真的很糟糕....这意味着你可能会使用这种方式存储大量数据而毫无意义。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接