本篇重点是性能优化,包括内容:
- 布局优化
- 绘制优化
- 内存泄漏优化
- MAT工具
- 响应速度优化
- ListView优化
- Bitmap优化
- 线程优化
- 其他
1.布局优化
a.核心思想:尽量减少布局文件的层级。
b.方式:
- 多嵌套情况下可使用RelativeLayout减少嵌套。
- 布局层级相同的情况下使用LinearLayout,它比RelativeLayout更高效。
- 使用
<include>
标签重用布局、<merge>
标签减少层级、<ViewStub>
标签懒加载。详见布局篇--布局原则
补充实例: Android最佳性能实践--布局优化技巧
2.绘制优化
a.核心思想:避免在View.onDraw()
中执行大量的操作。
b.方式:
- 避免创建新的局部对象,因为
onDraw()
可能被多次调用而产生大量的临时对象,导致占用过多内存、系统频繁gc,降低了执行效率。 - 避免做耗时任务,以及大量循环操作。
3.内存泄漏优化
a.内存泄漏(Memory Leak):程序在申请内存后,无法释放已申请的内存空间。是造成应用程序OOM的主要原因之一。
内存溢出(out of memory):指程序在申请内存时,没有足够的内存空间供其使用。
补充阅读:内存溢出和内存泄漏的区别
b.可能原因:
- 静态变量导致的内存泄漏
- 详情:一个静态变量又是非静态内部类会一直持有对外部类的引用,导致外部类Activity无法被回收。
- 解决办法:将内部类设为静态内部类或独立出来;使用
context.getApplicationContext()
。
- 单例模式导致的内存泄漏
- 详情:单例传入参数this来自Activity,使得持有对Activity的引用。
- 解决办法:传参
context.getApplicationContext()
。
- 属性动画导致的内存泄漏
- 详情:没有在
onDestroy()
中停止无限循环的属性动画,使得View持有了Activity。 - 解决办法:在
Activity.onDestroy()
中调用Animator.cancel()
停止动画。
- 详情:没有在
- Handler导致的内存泄漏
- 详情:Message持有对Handler的引用,而非静态内部类的Handler又隐式持有对外部类Activity的引用,使得引用关系会保持至消息得到处理,从而阻止了Activity的回收。
- 解决办法:使用静态内部类+WeakReference弱引用;当外部类结束生命周期时清空消息队列。
- 线程导致的内存泄漏
- 详情:AsyncTask/Runnable以匿名内部类的方式存在,会隐式持有对所在Activity的引用。
- 解决办法:将AsyncTask和Runnable设为静态内部类或独立出来;在线程内部采用弱引用保存Context引用。
- 资源未关闭导致的内存泄漏
- 详情:未及时注销资源导致内存泄漏,如BraodcastReceiver、File、Cursor、Stream、Bitmap等。
- 解决办法:在Activity销毁的时候要及时关闭或者注销。
- BraodcastReceiver:调用
unregisterReceiver()
注销; - Cursor,Stream、File:调用
close()
关闭; - Bitmap:调用
recycle()
释放内存(2.3版本后无需手动)。
- BraodcastReceiver:调用
- Adapter导致的内存泄漏
- 详情:不使用缓存而只依靠
getView()
每次重新实例化Item,会给gc制造压力。 - 解决办法:在构造Adapter时使用缓存的convertView。
- 详情:不使用缓存而只依靠
c.方式:
- 在开发过程中避免写出内存泄漏的代码,可参考以上多种解决办法。
- 通过分析工具如MAT寻找潜在的内存泄漏。
推荐阅读:常见的内存泄漏原因及解决方法
4.响应速度优化
a.核心思想:避免在主线程中做耗时操作。
b.方式:开线程。
5.ListView优化
- 复用ViewHolder,具体使用;
- 不要在
getView()
中执行耗时操作; - 开启硬件加速。
综合实例:ListView终极优化方法
6.Bitmap优化
- 利用BitmapFactory.Options的inSampleSize属性,根据需求对图片进行采样后再加载进来。详见Bitmap的高效加载
7.线程优化
- 采用线程池,避免存在大量的Thread。详见线程&线程池
8.其他
- 避免创建过多的对象 ;
- 不要过多使用枚举,枚举占用的内存空间要比整型大;
- 常量请使用static final来修饰;
- 使用一些Android特有的数据结构,比如SparseArray和Pair等,它们都具有更好的性能;
- 适当使用软引用和弱引用;
- 采用内存缓存和磁盘缓存;
- 尽量采用静态内部类,这样可以避免潜在的由于内部类而导致的内存泄露。
推荐阅读:Android开发性能优化总结、 Android最佳性能实践系列
最后,是有助于提高程序可维护性的几点建议,一起共勉:
希望这篇文章对你有帮助~