15.1 布局优化
思想:尽量减少布局文件的层级
- 若布局中既可以使用LinearLayout,也可以使用RelativeLayout,那么就采用LinearLayout。RelativeLayout功能比较复杂,布局过程需要花费更多的CPU时间
- FrameLayout和LinearLayout一样都是一种简单高效的ViewGroup
- 若需要通过嵌套方式实现效果,建议采用RelativeLayout,因为ViewGroup的嵌套就相当于增加了布局的层级,同样会降低程序的性能。
- 采用< include >标签,< merge >标签和ViewStub
< include >标签主要用于布局重用
< merge >标签一般和< include >配合使用,降低布局的层级
ViewStub提供了按需加载的功能,需要时才会将ViewStub中的布局加载到内存
15.1.1 标签
- 将一个指定的布局文件加载到当前的布局文件中
- 只支持以android:layout_开头的文件
<include layout="@layout/titlebar"/>
15.1.2 标签
< merge >标签一般和< include >配合使用,降低布局的层级
例如:当前是一个竖直方向的LinearLayout,这时如果被包含的也采用了竖直的LinearLayout,被包含的布局文件中的LinearLayout是多余的,通过标签可以去掉多余的那一层
15.1.3 ViewStub
继承了View,非常轻量级且宽/高都是0,不参与任何的布局和绘制,意义在于按需加载所需的布局文件。
例如:实际开发中很多布局文件在正常情况下不会显示,如网络异常时的界面,这时没有必要在整个界面初始化时将其加载进来,通过ViewStub就可以做到在使用的时候再加载。
使用:
((ViewStub) findViewById(R.id.stub_import)).setVisibility(View.VISIBLE);
// 或者:
View importPanel = ((ViewStub) findViewById(R.id.stub_import)).inflate();
不支持< merge >标签
15.2 绘制优化
指View的onDraw方法要避免执行大量的操作
- onDraw中不要创建新的布局对象。onDraw方法可能会被频繁调用,会在一瞬间产生大量的临时对象
- onDraw中不要做耗时的任务
15.3 内存泄漏优化
- 避免写出有内存泄漏的代码
- 通过一些分析工具如MAT找出潜在的内存泄漏
场景1:静态变量导致的内存泄漏
场景2:单例模式导致的内存泄漏
场景3:属性动画导致的内存泄漏
无限循环的动画,若在Activity中播放此类动画且没有在onDestory中停止,最终 Activity无法释放
解决方法:在Activity的onDestory中调用animator.cancel()来停止动画
15.4 响应速度优化和ANR日志分析
响应速度优化:避免在主线程中做耗时操作,放到线程中去执行,采用异步的方式执行耗时 操作
ANR日志分析:当一个进程发生了ANR后,系统会在/data/anr 目录下创建一个文件traces.txt
15.5 ListView和Bitmap优化
ListView优化:
- 采用ViewHolder并避免在getView中执行耗时操作
- 根据列表的滑动状态来控制执行任务的执行效率(当列表快速滑动时显然不太适合开启大量的异步任务)
- 尝试开启硬件来加速使ListView的滑动更加流畅
(也适用于GridView)
Bitmap优化:
主要通过BitmapFactory.Options来根据需要对图片进行采样
15.6 线程优化
采用线程池,避免程序中存在大量的Thread
线程池可以重用内部的线程,避免线程的创建和销毁带来的性能开销
还能有效地控制线程池的最大并发数,避免大量的线程因互相抢占系统资源从而导致阻塞现象的发生
在实际开发中,尽量采用线程池
15.7 一些性能优化的建议
- 避免创建过多的对象
- 不要过多使用枚举,枚举占用的内存空间比整形大
- 常量请使用static final来修饰
- 使用一些Android特有的数据结构,如SparseArray 和 Pair等,有更好的性能
- 适当使用软引用和弱引用
- 采用内存缓存和磁盘缓存
- 尽量采用静态内部类,可以避免潜在的由于内部类而导致的内存泄漏