关于Android 性能最常见的一个问题是,在你的代码中使用enum(枚举)。真的,这个问题到处都会遇到,在Stack Overflow(堆栈溢出),在我们常见问题解答中,甚至在本地食品柜台的便餐中。呃,好了,我是Colt McAnlis, Android应用中的enum(枚举)既难又不难,所以才会导致困扰。先讲个故事。2009年时developers.android.com上有个网页,说为了性能,要避免使用枚举。然后几乎没解释,它就消失了。然后,当然他又回来了,只不过规模更小。所以故事是什么呢?事实有些细微差别,而且和性能与内存膨胀之间的差别有着很大的关系。
当你的应用被载入时,Android会为你的应用留出一定的系统内存。为了让你的应用运行,他的所有DEX代码都被载入到那个子空间。但,当然了,为了你的应用进行的运行环境配置。这个空间最后会和剩余的堆共享。但是幸好,它不和你的运行环境配置竞争。然而它的确会为系统内存施加压力。当然,这在内存降低时,会终止你的应用来释放空间。考虑到这一点,我们来看看你应用上的枚举的效果。
假如我们有一个小型数据库应用,它的整个DEX覆盖区是2556字节。现在我们要加入一些整数,它代表着系统可使用可返回的状态。重新编译后,DEX大小为2680字节。意味着这些整数在代码大小方面,已经添加了可执行的额外的124字节到我们的数据库。为了对比,我们还是用这个数据库应用,但是对它使用枚举而不是整数。结果DEX大小为4188字节。所以在代码中加入一个枚举,就增加了1632字节到最后的DEX大小。或者对你们当中数学特别棒的人来说,差不多是INT 版本内存的13倍。这俄当然会让你的DEX文件膨胀,这也会消耗你的堆空间。可是,如果这个还不够糟糕。还有运行缓建内存花费需要担心呢。通常,每一个枚举值,宣告会额外花费你将近20字节。当然了,还需要对象散列来跟踪枚举值。这个还需要再花费12字节。在Dalvik上是16字节。
总之,你代码中每一个枚举宣告需要的额外的花费,意味着你的应用使用的枚举越多,消耗的空间就越大。而这整件事比你想象中更容易失控。比如,如果你的应用广泛的使用枚举,或者它们在设备上某个被大量应用使用的库中。这些小的花费很快就会积累为大量花费。最糟糕的是,在枚举感染了你的代码基础之前,你都不会知道枚举造成了问题。到那时,修复它可就是个可怕的过程了。这样想,枚举像个小恶魔,它们本身一两个并不会造成问题,你可以用卷起来的报纸或者棒球棍解决它们,如果可能的话,顺手拿起火焰喷射器对付它们,对吧?但是当它们大量聚集时,麻烦就大了,你会希望真的有火焰喷射器。所以Core Platform Team(核心平台团队)会实际上编写Android代码的那些人,有一个强烈的建议,避免在他们写的代码的任何位置使用枚举。显然他们对潜在问题更有前瞻性,而不是只能反应应对。考虑到这个,有几件事你要考虑,来解决这个问题。
首先,如果你在值对象上使用整数而不是枚举,你可以向它们添加@IntDef注释,这在Lint错误启动时,可以给你的代码建造时安全,还能保持大小和利用整数变量的性能优势。这让我能可以使用两个方法的优点。第二,如果你的代码设置正确,Proguard(混淆器)可以在很多情况下帮你将枚举优化到整数值对象。这样你就不用费心或者操作了。这一点很可能会给你的应用免费带来一点性能提升。而大部分情况下性能提升都是要争取的。
相关链接:
Shrink Your Code and Resources
本文抄录自: