在 Android 中使用 Serializable 不好吗?

Posted

技术标签:

【中文标题】在 Android 中使用 Serializable 不好吗?【英文标题】:Is using Serializable in Android bad? 【发布时间】:2011-04-06 10:13:27 【问题描述】:

我已经阅读了很多赞美 Parcelable 优于 Serializable 的速度的帖子和文章。我已经使用了一段时间来通过 Intents 在活动之间传递数据,并且在两者之间切换时还没有注意到任何速度差异。我必须传输的典型数据量是 5 到 15 个嵌套对象,每个对象包含 2 到 5 个字段。

由于我有大约 30 个必须可转移的类,因此实现 Parcelable 需要大量样板代码,这会增加维护时间。我目前的要求之一也是编译后的代码应该尽可能小;我希望我可以通过使用 Serializable 而不是 Parcelable 来节省一些空间。

我应该使用 Parcelable 还是没有理由在 Serializable 上使用它来处理如此少量的数据?还是我不应该使用 Serializable 的其他原因?

【问题讨论】:

您是否在低功率设备上测试过速度差异?速度差异是真实的.. 这个链接的问题有更多的基准:***.com/questions/3323074/… 【参考方案1】:

对于内存使用,Parcelable 比 Serializable 要好得多。我强烈建议不要使用 Serializable。

您不能将 Parcelable 用于将存储在磁盘上的数据(因为当事情发生变化时它不能很好地保证数据的一致性),但是 Serializable 足够慢,我强烈建议不要在那里使用它。你最好自己写数据。

此外,Serializable 的性能问题之一是它最终会遍历大量临时对象,从而在您的应用中导致大量 GC 活动。真是太可恶了。 :

【讨论】:

你是绝对正确的。但是,您始终可以通过将其转换为 JSON 字符串来持久保存它。 如果您说要将 parcel 保存到 JSON 字符串中...不,不,您不能。将其重新编码为 JSON 字符串并不会改变这样一个事实,即其中的数据不保证数据与事物变化的一致性,也不具有保证跨平台版本相同的格式。 在构建应用程序时,SDK 本身不能做额外的工作,以便在运行时不使用反射吗? 您是否有任何证据来支持您的说法“对于内存使用,Parcelable 远远优于 Serializable”?根据我的测试,它比 Serializable 要慢得多。 @nucleo 通常的比较是自动序列化与可打包(developerphil.com/parcelable-vs-serializable)。手动序列化比自动序列化更快,但与 Parcelable 有相同的维护缺点。关于 Parcelable 与手动 Serializable,罪魁祸首可能是 Parcel.writeValue,请参阅问题:bitbucket.org/afrishman/androidserializationtest/issues/1/…【参考方案2】:

继续使用序列化。您会在网上看到很多人会告诉您,序列化非常缓慢且效率低下。那是正确的。但是,作为一名计算机程序员,你永远不想做的一件事是将任何关于性能的评论视为绝对的。

问问自己,序列化是否会减慢您的程序速度。您是否注意到它从一个活动到另一个活动?您是否注意到它何时保存/加载?如果没有,那很好。当您使用大量手动序列化代码时,您不会获得更小的足迹,因此没有任何优势。那么,如果慢 100 倍意味着 10 毫秒而不是 0.1 毫秒,那么如果它比替代方案慢 100 倍呢?你也不会看到,所以谁在乎呢?而且,如果没有明显的性能差异,为什么有人会投入大量精力为 30 个类编写手动序列化?

【讨论】:

更好的是,根据我的观察,通常的 Java 序列化(如果操作正确)比 Parcelable 快得多。请参阅下面我的答案中的详细信息。【参考方案3】:

每个人都只是盲目地说 Parcelable 比 Serializable 更好更快,但是没有人试图用任何证据来支持他的陈述。我决定自己测试一下,结果非常有趣。

普通 Android 设备上的常规 Java 序列化(如果操作正确)在写入方面比 Parcelable 快大约 3.6 倍,在读取方面大约快 1.6 倍。

你可以在这里查看我的测试项目:https://github.com/afrish/androidserializationtest

【讨论】:

@damson 这就是为什么我称之为“正确的序列化”。在上面每个人都提到的文章中,序列化并没有充分发挥其潜力。这是不公平的比较。在我的基准测试中,我试图让它更公平,结果完全不同。问题是每个人都“忘记”了 writeObject() / readObject() 方法,这些方法可以让 Java 内置序列化快速而不会弄乱 Parcelable 等平台特定的东西。 我完全同意。实际上我觉得,既有有用又安静的等价物,但这取决于您的应用程序的场景。这里有另一篇文章将 ligth 这次放在 Serializable nemanjakovacevic.net/blog/english/2015/03/24/… 没有注意到您的评论也是答案,我的评论在其他地方适用:***.com/questions/3611843/… 这是一个很好的基准测试,但我认为它不能反映Serializable 在Android 项目中的使用方式,即没有writeObject 方法“覆盖”。如果没有这些覆盖,将使用反射,并且根据***.com/questions/3323074/…中的答案,可序列化会更慢@ @DmitriyPavlukhin 这是一个非常古老的项目,已有 6 年多的历史了。我将它转移到 GitHub 并编辑了链接。不确定它是否仍然运行:)【参考方案4】:

有没有人考虑过使用 JSON 进行序列化并将数据作为字符串传递? GSON 和 Jackson 的效率应该足以成为 Parcelable 和 Serializable 的竞争对手。

【讨论】:

以上是关于在 Android 中使用 Serializable 不好吗?的主要内容,如果未能解决你的问题,请参考以下文章

可序列化是啥意思?

RandomAccess 接口,为啥没有方法?

在没有序列化的情况下克隆对象

Spring Security 登录不起作用

hibernate丢失更新

互联网JAVA面试常问问题