通过bundle检索parcelable对象是否始终创建新副本?

时间:2016-10-07 11:23:15

标签: android android-fragments parcelable android-bundle

我通过在创建片段时添加到一个包中将一个parcelable对象传递给一个片段。在onc实例中,对此parceled对象的修改反映了原始对象的修改,而在另一种情况下则不是。我对这种行为感到有点困惑。 直到现在我已经假设通过一个包检索一个包围的对象总是创建一个新对象[不确定它是浅拷贝还是深拷贝]。

有人请澄清可以行动的行为。

1 个答案:

答案 0 :(得分:16)

我正在努力解决类似的问题。乍一看,似乎我们总是从包围的对象中获取新的深层副本。此外,甚至有some StackOverflow答案建议使用Parcelable接口来克隆对象。所有这些只会增加对该主题的混淆。

以下是我经过大量搜索和谷歌搜索后发现的内容:

  • 仔细查看官方Parcel documentation。这是重要的一句话:
  

Parcel的一个不寻常的功能是读写活动的能力   对象。对于这些对象,对象的实际内容不是   写入,而不是引用该对象的特殊标记。   从包裹中读回物体时,不会得到新物品   对象的实例,而是一个对其进行操作的句柄   与最初编写的完全相同的对象。

好的,正如您所看到的,有一些特殊对象在取消期间没有被复制。但这仍然有点令人困惑。这是否意味着我们对原始对象有另一个强引用,以防止其垃圾收集?这些对象的用例是什么?

  • 为了回答上述问题,我决定浏览Android source code。我正在寻找的方法是readStrongBinderwriteStrongBinder,根据文档,在发送/接收包裹时不会导致新的对象创建。我想我在ResultReceiver.java课程中找到了理想的答案。这是有趣的路线:

    mReceiver = IResultReceiver.Stub.asInterface(in.readStrongBinder());
    

    要了解这条线实际上在做什么,我们应该去官方AIDL documentation。以下是最重要的部分:

  

调用类必须采取的步骤来调用已定义的远程接口   与AIDL:
  ......   5.在onServiceConnected()的实现中,您将收到一个   IBinder实例(称为服务)。呼叫    YourInterfaceName.Stub.asInterface((IBinder)服务)来投射   将参数返回到YourInterface类型。

     

关于呼叫IPC服务的一些意见:

     

对象在各个流程中引用计数

所以让我们将所有事情放在一起:

  1. 可以在不涉及深层复制过程的情况下提取分区对象。
  2. 如果使用readStrongBinder方法读取分区对象,则不会创建新实例。我们只是获得了对原始对象的新引用,这个引用可以防止它的交易分配。
  3. 要知道在收到包裹后我们的对象是否会被深层复制,我们应该仔细查看具体的Parcelable接口实现。
  4. Android文档可能会让人感到困惑,可能需要花费大量时间才能正确理解它。
  5. 希望这些信息对您有所帮助。

    如果您想了解有关Parcelable对象的混淆可能导致严重问题的真实示例,请查看我的blog post