【发布时间】:2016-10-07 11:23:15
【问题描述】:
我通过在创建片段时添加到包中来将可打包对象传递给片段。在一个实例中,对这个打包对象的修改反映了对原始对象的修改,而在另一种情况下则不是。我对这种行为有点困惑。 到目前为止,我假设通过捆绑检索打包的对象总是会创建新对象[不确定它是浅拷贝还是深拷贝]。
请有人澄清可打包的行为。
【问题讨论】:
标签: android android-fragments parcelable android-bundle
我通过在创建片段时添加到包中来将可打包对象传递给片段。在一个实例中,对这个打包对象的修改反映了对原始对象的修改,而在另一种情况下则不是。我对这种行为有点困惑。 到目前为止,我假设通过捆绑检索打包的对象总是会创建新对象[不确定它是浅拷贝还是深拷贝]。
请有人澄清可打包的行为。
【问题讨论】:
标签: android android-fragments parcelable android-bundle
我正在努力解决类似的问题。乍一看,我们似乎总是从打包的对象中获得一个新的深拷贝。此外,甚至还有some StackOverflow 的答案建议使用Parcelable 接口来克隆对象。所有这些只会增加对该主题的混淆。
这是我经过大量搜索和谷歌搜索后发现的:
Parceldocumentation。这是重要的引述:Parcel 的一个不同寻常的功能是能够主动读写 对象。对于这些对象,对象的实际内容不是 写入,而是写入引用对象的特殊标记。 从包裹中读取对象时,您不会得到新的 对象的实例,而是在 与最初编写的对象完全相同。
好的,如您所见,有一些特殊的对象在解包过程中没有被复制。但这仍然有点令人困惑。这是否意味着我们对阻止其垃圾收集的原始对象有另一个强引用?这些对象的用例是什么?
为了回答上述问题,我决定查看 Android source code。我正在寻找的方法是readStrongBinder 和writeStrongBinder,根据文档,它们在发送/接收包裹时不会导致新的对象创建。我想我在ResultReceiver.java 类中找到了想要的答案。这是有趣的一行:
mReceiver = IResultReceiver.Stub.asInterface(in.readStrongBinder());
要了解这条线实际上在做什么,我们应该去官方AIDL documentation。以下是最重要的部分:
调用类必须采取的步骤来调用定义的远程接口 与 AIDL:
...
5. 在你的 onServiceConnected() 实现中,你会收到一个 IBinder 实例(称为服务)。称呼 YourInterfaceName.Stub.asInterface((IBinder)service) 来转换 将参数返回到 YourInterface 类型。关于调用 IPC 服务的几个 cmets:
对象被引用计数跨进程。
让我们把所有东西放在一起:
readStrongBinder 方法读取打包对象,则不会创建新实例。我们只是获取一个对原始对象的新引用,这个引用可以防止它被释放。Parcelable 接口实现。希望这些信息对您有所帮助。
如果您想了解一个真实的示例,当关于 Parcelable 对象的混淆会导致严重问题时,请查看我的 blog post。
【讨论】: