这里根据网络上各位大神已经总结的知识内容作一个大汇总,做为记录,方便后续“温故知新”。html
(1)使用流畅度:android
图片处理器每秒刷新的帧数(FPS),可用来指示页面是否平滑的渲染。高的帧率能够获得更流畅,更逼真的动画,不过帧率达到60fps以上,人眼主观感觉到的差异就不大了。因此以60fps做为衡量标准,即要求每一帧刷新的时间小于16ms,这样才能保证滑动中平滑的流畅度。编程
(2)内存使用状况: 数组
在android系统中,每一个APP进程除了同其余进程共享(shared dirty)外,还独用私有内存(private dirty),一般咱们使用PSS(=私有内存+比例分配共享内存)来衡量一个APP的内存开销。移动设备的内存资源是很是有限,为每一个APP进程分配的私有内存也是有限制。一方面咱们要合理的申请内存使用,以避免致使频繁的GC影响性能和大对象申请发生内存溢出;另外一方面,咱们要及时释放内存,以避免发生内存泄漏。缓存
(3)电量使用状况:性能优化
相对于PC来讲,移动设备的电池电量是很是有限的,保持持久的续航能力尤其重要。另外,android的不少特性都比较耗电(如屏幕,GPS,sensor传感器,唤醒机制,CPU,连网等的使用),咱们必需要慎重检查APP的电量使用,以避免致使用户手机耗电发热,带来不良体验。网络
(4)流量使用状况:app
目前的网络类型包含2G\3G\4G\wifi,其中还有不一样运营商的区分,咱们在APP的使用中常常遇到大资源,重复请求,调用响应慢,调用失败等各类状况。在不一样的网络类型之下,咱们不只要控制流量使用,还须要加快请求的响应。框架
原理及相关知识介绍请参考google官方的教程:函数
具体优化方案:
1、使用优化后的数据容器:
请使用 Andorid 框架中优化过的数据容器,例如 SparseArray,SparseBooleanArray 和 LongSparseArray。相似于 HashMap 这一类的容器的效率不是很高,由于在每一个 Map 中对于每一次的存放数据,他都须要独立一个单独的 Entry 对象进行传芳。而 SparseArray 因为禁止系统自动封装键值对,所以他更加有效率。而且你不须要担忧丢失掉原有信息。
2、尽可能避免使用枚举类型:
枚举与静态常量相比,一般会消耗两倍的内存资源。
三、避免建立没必要要的对象:(特别是在onDraw相似的函数里)
建立太多的对象会形成性能低下,这谁都知道,但是为何呢?首先分配内存自己须要时间,其次虚拟机运行时堆内存使用量是有上限的,当使用量到达必定程度时会触发垃圾回收,垃圾回收会使得线程甚至是整个进程暂停运行。可想而知,若是有对象频繁的建立和销毁,或者内存使用率很高,就会形成应用程序严重卡顿。(内存抖动)
四、合理使用static成员:
主要有三点须要掌握:
(1)若是一个方法不须要操做运行时的动态变量和方法,那么能够将方法设置为static的。
(2)常量字段要声明为“static final”,由于这样常量会被存放在dex文件的静态字段初始化器中被直接访问,不然在运行时须要经过编译时自动生成的一些函数来初始化。此规则只对基本类型和String类型有效。
(3)不要将视图控件声明为static,由于View对象会引用Activity对象,当Activity退出时其对象自己没法被销毁,会形成内存溢出。
五、 使用for-each循环:
加强的For循环(也被称为 for-each 循环)能够被用在实现了 Iterable 接口的 collections 以及数组上。使用collection的时候,Iterator (迭代器,译者注) 会被分配,用于for-each调用 hasNext()
和 next()
方法。使用ArrayList时,手写的计数式for循环会快3倍(无论有没有JIT),可是对于其余collection,加强的for-each循环写法会和迭代器写法的效率同样。
请比较下面三种循环的方法:
static class Foo { int mSplat; } Foo[] mArray = ... public void zero() { int sum = 0; for (int i = 0; i < mArray.length; ++i) { sum += mArray[i].mSplat; } } public void one() { int sum = 0; Foo[] localArray = mArray; int len = localArray.length; for (int i = 0; i < len; ++i) { sum += localArray[i].mSplat; } } public void two() { int sum = 0; for (Foo a : mArray) { sum += a.mSplat; } }
zero()是最慢的,由于JIT没有办法对它进行优化。
one()稍微快些。
two() 在没有作JIT时是最快的,但是若是通过JIT以后,与方法one()是差很少同样快的。它使用了加强的循环方法for-each。
因此请尽可能使用for-each的方法,可是对于ArrayList,请使用方法one()。
你还能够参考 Josh Bloch 的 《Effective Java》这本书的第46条
六、避免使用浮点类型:
经验之谈,所在Android设备中浮点型大概比整型数据处理速度慢两倍,以若是整型能够解决的问题就不要用浮点型。另外,一些处理器有硬件乘法可是没有除法,这种状况下除法和取模运算是用软件实现的。为了提升效率,在写运算式时能够考虑将一些除法操做直接改写为乘法实现,例如将“x / 2”改写为“x * 0.5”。
七、了解并使用库函数:
Java标准库和Android Framework中包含了大量高效且健壮的库函数,不少函数还采用了native实现,一般状况下比咱们用Java实现一样功能的代码的效率要高不少。因此善于使用系统库函数能够节省开发时间,而且也不容易出错。
八、避免依赖注入框架:
使用相似于 Guice 和 RoboGuice 的依赖注射框架,或许会使你的代码变得更加漂亮,由于他们可以减小你须要写的代码,而且为测试或者在其余条件改变的状况下,提供一种自适应的环境。可是,这些框架在初始化的时候会由于注释而消耗大量的工做在扫描你的代码上,这会让你的代码在进行内存映射的时候花费更多的资源。虽然这些内存可以被 Android 进行回收,可是等待整个分页被释放须要很长一段时间。
九、当心使用外部依赖包:
不少依赖包都不是专门为了移动环境或者移动客户端写的。若是你决定使用一个外部依赖包,你应该提早明白你须要为了将它移植到移动端而消耗花费大量的时间和工做量。请在使用外部依赖包得时候提早分析他的代码和内存占用
即便依赖包是为了 Android 而设计的,可是这也有潜伏的危险,由于每个包都作着不一样的工做。例如,有一个依赖包使用纳米级的 protobufs 可是别的包使用微米级的 protobufs.那么如今在你的应用中就有两套 protobuf 的标准了。这会在你记录数据,分析数据,加载图像,缓存,或者其余任何可能的状况下发生你不但愿发生的事情。ProGuard 没法在这里帮助你,由于他们都是你所依赖包的底层实现,。当你使用从别的依赖包(他可能继承了不少的依赖包)里继承的 Activity 时,这个问题变得尤为严重,当你使用反射以及干别的事情的时候
请注意不要落入一个依赖包的陷阱,你不但愿引入一大片你根本不会使用到的代码。若是你没法找到一种已经实现的逻辑来彻底知足你的需求,那么你尽可能建立一个本身的实现方式。
十、避免内部的Getters/Setters:
像C++等native language,一般使用getters(i = getCount())而不是直接访问变量(i =mCount)。这是编写C++的一种优秀习惯,并且一般也被其余面向对象的语言所采用,例如C#与Java,由于编译器一般会作inline访问,并且 你须要限制或者调试变量,你能够在任什么时候候在getter/setter里面添加代码。然而,在Android上,这是一个糟糕的写法。虚函数的调用比起直接访问变量要耗费更多。在面向对象编程中,将getter和setting暴露给公用接口是合理的,但在类内部应该仅仅使用域直接访问。在没有JIT(Just In Time Compiler)时,直接访问变量的速度是调用getter的3倍。有JIT时,直接访问变量的速度是经过getter访问的7倍。请注意,若是你使用 ProGuard , 你能够得到一样的效果,由于ProGuard能够为你inline accessors.