在Android中使用Serializable是不好的吗?

57

我一直在阅读很多赞扬Parcelable速度优于Serializable的帖子和文章。我使用这两种方式已经有一段时间了,通过Intents在Activities之间传递数据。然而,当我在两种方式之间切换时,我还没有注意到任何速度差异。我需要传输的典型数据量是5到15个嵌套对象,每个对象有2到5个字段。

由于我有大约30个必须可传输的类,实现Parcelable需要大量样板代码,这增加了维护时间。我的一个当前要求也是编译后的代码尽可能小; 我认为我可以通过使用Serializable而不是Parcelable来节省一些空间。

对于这么少量的数据,我应该使用Parcelable还是没有理由使用它而不使用Serializable?或者还有其他原因我不应该使用Serializable吗?


你测试过低功率设备的速度差异吗?速度差异是真实存在的。 - Cheryl Simon
这个链接的问题有更多的基准测试:https://dev59.com/V3A75IYBdhLWcg3wYYBQ - David Rawson
4个回答

68

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

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

此外,Serializable存在性能问题之一是它往往会旋转大量临时对象,导致应用程序中出现大量GC活动。这相当可怕。:}


如果你想将一个包裹持久化为JSON字符串...不,不行。将其重新编码为JSON字符串并不能改变其中的数据没有关于数据一致性的保证,当事物发生变化或格式在平台版本之间保证相同时。 - hackbod
不要持久化“parcel”(指Android中的包裹对象)。但是可以持久化该“object”(对象)。 - johan
1
SDK本身是否可以在构建应用程序时完成额外的工作,以便在运行时不使用反射? - android developer
5
你有任何证据支持你的说法“对于内存使用,Parcelable远远优于Serializable”吗? 我的测试结果表明它比Serializable慢得多。 - afrish
1
@nucleo 通常比较的是自动序列化和Parcelable(http://www.developerphil.com/parcelable-vs-serializable/)。手动序列化比自动序列化更快,但具有Parcelable的相同维护缺点。关于Parcelable与手动Serializable的比较,罪魁祸首可能是Parcel.writeValue,请参见问题: https://bitbucket.org/afrishman/androidserializationtest/issues/1/writelist-vs-open-coding - Blaisorblade
显示剩余3条评论

58

继续使用序列化。在网上有很多人会告诉你序列化非常慢且效率低下,这是正确的。但是,作为计算机程序员,你永远不应该将任何关于性能的评论视为绝对。

问问自己序列化是否会拖慢程序的运行速度。当它从一个活动转到另一个活动时,你是否会注意到它?当它保存/加载时,你是否会注意到它?如果没有,那就没事了。如果你要编写大量手动序列化代码,你不会得到更小的占用空间,因此没有任何优势。如果100倍慢于替代方案,但100倍慢意味着10毫秒而不是0.1毫秒,那又怎样呢?你不会看到任何区别,所以谁在乎呢?并且,为什么会有人花费大量精力为30个类编写手动序列化,而对性能没有任何可感知的差异呢?


2
更好的是,根据我的观察,通常情况下,如果正确使用,Java序列化比Parcelable更快。请参见下面我的回答中的详细信息。 - afrish

20

大家都盲目地声称Parcelable比Serializable更好、更快,但是没有人试图用任何证据来支持这种说法。我决定自己测试一下,结果非常有意思。

在平均Android设备上(如果正确实现),通常的Java序列化写入速度约为Parcelable的3.6倍,读取速度约为1.6倍。

您可以在此处检查我的测试项目:https://github.com/afrish/androidserializationtest


3
这就是我称它为“正确完成序列化”的原因。在上述文章中,所有人都提到的是,序列化没有充分利用。这是不公平的比较。在我的基准测试中,我尝试使它更加公平,并且结果完全不同。问题在于每个人都“忘记”了writeObject()/readObject()方法,这些方法可以让Java内置的序列化变得非常快,而不必涉及像Parcelable这样的特定于平台的东西。 - afrish
3
我完全同意。实际上,我感觉有些情况下两者都有用但取决于你的应用场景。这里有另一篇文章,这次是关于Serializable的: http://nemanjakovacevic.net/blog/english/2015/03/24/yet-another-post-on-serializable-vs-parcelable/ - damson
没有注意到你的评论也是一个答案,我在其他地方的评论适用:https://dev59.com/KXA65IYBdhLWcg3w1SRC#z9HonYgBc1ULPQZFAhM5 - Blaisorblade
这是一个不错的基准,但我认为它并没有反映出Serializable在Android项目中的实际使用方式,即没有writeObject方法重写。如果没有这些重写,将会使用反射,并且根据 https://dev59.com/V3A75IYBdhLWcg3wYYBQ 中的答案,序列化将会更慢。 - David Rawson
这个答案的链接已经失效了,你能修复一下吗? - Dmitriy Pavlukhin
1
@DmitriyPavlukhin 这是一个非常古老的项目,已经超过6年了。尽管我将其转移到了GitHub并编辑了链接,但不确定它是否仍在运行:) - afrish

1

有没有人考虑使用JSON进行序列化,并将数据作为字符串传递?GSON和Jackson应该足够高效,可以与Parcelable和Serializable竞争。


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