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

ape*_*ite 12 android parcelable android-fragments android-bundle

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

有人请澄清可怜行为.

Sta*_*ots 17

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

这是我经过大量搜索和谷歌搜索后发现的:

  • 仔细看看官方Parcel 文档.这是重要的引用:

Parcel的一个不寻常的特性是能够读取和写入活动对象.对于这些对象,不写入对象的实际内容,而是写入引用该对象的特殊标记.从Parcel中读取对象时,您不会获得该对象的新实例,而是获取与最初编写的完全相同的对象进行操作的句柄.

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

  • 为了回答上述问题,我决定查看Android 源代码.我一直在寻找的方法是 readStrongBinderwriteStrongBinder其中根据文档不会引起创建新对象时,包裹都发送/接收.我想我在ResultReceiver.java类中找到了所需的答案.这是有趣的路线:

    mReceiver = IResultReceiver.Stub.asInterface(in.readStrongBinder());
    
    Run Code Online (Sandbox Code Playgroud)

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

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

关于调用IPC服务的几点意见:

对象是跨进程的引用计数.

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

  1. 可以在不涉及深度复制过程的情况下提取分区对象.
  2. 如果使用readStrongBinder方法读取parceled对象,则不会创建新实例.我们只是获得了对原始对象的新引用,这个引用可以防止它的交易分配.
  3. 要知道在收到包裹后我们的对象是否会被深层复制,我们应该仔细研究具体的Parcelable接口实现.
  4. Android文档可能非常混乱,可能需要花费大量时间才能正确理解它.

希望这些信息对您有所帮助.

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