文档介绍:编写高效的Android代码
简介
尽可能避免创建对象(Object)
使用自身方法(Use Native Methods)
使用虚拟优于使用接口
使用静态优于使用虚拟
尽可能避免使用内在的Get、Set方法
缓冲属性调用Cache Field Lookups
声明Final常量
慎重使用增强型For循环语句
避免列举类型Avoid Enums
通过内联类使用包空间
避免浮点类型的使用
一些标准操作的时间比较
结束语
简介
毫无疑问,基于Android平台的设备一定是嵌入式设备。现代的手持设备不仅仅是一部电话那么简单,它还是一个小型的手持电脑,但是,即使是最快的最高端的手持设备也远远比不上一个中等性能的桌面机。
这就是为什么在编写Android程序时要时刻考虑执行的效率,这些系统不是想象中的那么快,并且你还要考虑它电池的续航能力。这就意味着没有多少剩余空间给你去浪费了,因此,在你写Android程序的时候,要尽可能的使你的代码优化而提高效率。
本页介绍了几种可以让开发者的Android程序运行的更加有效率的方法。通过下面的一些跳转的连接,你可以学会怎么让你的程序更加有效运行
对于如何判断一个系统的不合理,这里有两个基本的原则:
不要做不必要做的事情。
尽可能的节省内存的使用。
下面的所有方法都是基于这两项的。
有人会认为本页花了大量的篇幅去讲如何进行“初步优化”( premature optimization)。虽然有时候微观优化对开发高效的数据结构和算法很困难,但是在嵌入式手持设备上面你毫无选择。例如,如果把桌面电脑的虚拟机移植到你的Android系统中,你会发现你写的程序会耗尽你的内存。这就会导致程序运行起来极度缓慢,即使不考虑它对系统上其他的运行程序的影响。
这就是为什么上面两条原则这么重要。Android的成功在于开发程序提供给用户的体验,然而用户体验的好坏又决定于你的代码是否能及时的响应而不至于慢的让人崩溃。因为我们所有的程序都会在同一个设备上面运行,所以我们把它们作为一个整体来考虑。本文就像你考驾照需要学习的交通规则一样:如果所有人遵守,事情就会很流畅;但当你不遵守时,你就会撞车。
在我们讨论实质问题之前,有一个简要的说明:无论虚拟机是否是Java编译器的一个特点,下面介绍的所有观点都是正确的。如果我们有两种方法完成同样的事情,但是foo()的解释执行要快于bar(),那么foo()的编译速度一定不会比bar()慢,仅仅靠编译器使你的代码运行速度提升是不明智的做法。
尽可能避免创建对象(Object)
对象的创建并不是没有代价的。一个带有线程分配池的generational的内存管理机制会使创建临时对象的代价减少,不是分配内存总比不上不分配内存好。
如果你在一个用户界面的循环中分配一个对象,你不得不强制的进行内存回收,那么就会使用户体验出现稍微“打嗝”的现象。
因此,如果没有必要你就不应该创建对象实例。下面是一件有帮助的例子:
当从原始的输入数据中提取字符串时,试着从原始字符串返回一个子字符串,而不是创建一份拷贝。你将会创建一个新的字符串对象,但是它和你的原始数据共享数据空间。
如果你有一个返回字符串地方法,你应该知道无论如何返回的结果是StringBuffer,改变你的函数的定义和执行,让函数直接返回而不是通过创建一个临时的对象。
一个比较激进的方法就是把一个多维数组分割成几个平行的一维数组:
一个Int类型的数组要比一个Integer类型的数组要好,但着同样也可以归纳于这样一个原则,两个Int类型的数组要比一个(int,int)对象数组的效率要高的多。对于其他原始数据类型,这个原则同样适用。
如果你需要创建一个包含一系列Foo和Bar对象的容器(container)时,记住:两个平行的Foo[]和Bar[]要比一个(Foo,Bar)对象数组的效率高得多。(这个例子也有一个例外,当你设计其他代码的接口API时;在这种情况下,速度上的一点损失就不用考虑了。但是,在你的代码里面,你应该尽可能的编写高效代码。)
一般来说,尽可能的避免创建短期的临时对象。越少的对象创建意味着越少的垃圾回收,这会提高你程序的用户体验质量。
使用自身方法(Use Native Methods)
当处理字符串的时候,不要犹豫,()、()这样对象自身带有的方法。因为这些方法使用C/C++来实现的,要比在一个java循环中做同样的事情快10-100倍。
还有一点要补充说明的是,这些自身方法使用的代价要比那些解释过的方法高很多,因而,对于细微的运算,尽量不用这类方法。
使用虚拟优于使用接口
假设你有一个HashMap对象,你可以声明它是一个H