1、布局优化
include布局
引用已有视图
merge标签
合并布局管理器
ViewStub视图
延迟加载,在ViewStub调用inflate方法或设置visiable之前,它是不占用布局空间和系统资源的,只是一个占位符。加载视图之后,它就消失了,有加载后的布局替代。
减少视图层级
尽量多使用RelativeLayout,使视图变得扁平。
总结
- 尽量多使用RelativeLayout,不要使用绝对布局AbsoluteLayout
- 在ListView等列表组件中尽量避免使用LinearLayout的layout_weight属性
- 将可复用的组件抽取并使用include标签引用
- 使用ViewStub加载一些不是必要显示的布局
- 使用merge标签减少布局的嵌套层次
2、内存优化
a、珍惜Service资源
使用完Service就尽快停止它,系统会倾向于一直保留Service所在的进程,如果一个Service什么也没干,但是在一直运行,无疑就相当于内存泄漏了。推荐使用IntentService。
b、当UI隐藏时释放内存
可以实现Activity类里面的onTrimMemory回调方法,当你的UI不可见时,会在此方法收到TRIM_MEMORY_UI_HIDDEN级别的回调,此时就可以释放UI使用的资源。
与onStop的区别?
onStop会在Activity的实例被隐藏时执行,如,从一个Activity跳转到另一个Activity,此时应该在onStop中释放网络连接、解注册广播接受者等,释放Activity的资源。但是,除非收到onTrimMemory的TRIM_MEMOTRY_UI_HIDDEN参数的回调,否则不应该释放UI资源。这确保Activity返回时,可以迅速恢复UI。
c、当内存紧张时释放部分内存
在App生命周期的任意阶段,onTrimMemotry都会回调来通知内存开始紧张。它有很多参数来代表内存紧张的级别。
d、检查可使用的内存
- getMemoryClass可以获取heap大小
- 在application下设置largeHeap=true可以获取更大内存,相应的使用getLargeMemoryClass来获取heap大小
e、避免bitmaps的浪费
加载bitmap时,仅需要让Bitmap的数据达到当适配当前屏幕的分辨率即可,因为原图的分辨率如果大于屏幕分辨率,那就白白浪费了那么高清的数据了,还占用大量的内存。
2.3以下,bitmap的对象的pixel data存在native内存,3.0开始,bitmap pixel data分配在Dalvik heap中。
f、注意内存开销
Enums内存消耗通常是static constants的2倍,Java中每一个类都会使用大约500bytes,每个实例花销12-16bytes,在HashMap中添加一个entry会额外占用32bytes的entry对象
g、使用优化的数据容器
使用Android Framework里面优化过的容器类。SparseArray、SparseBoolArray、LongSparse。
h、代码“抽象”
抽象出来的组件在使用时,会被全部实例化,其中包含无用的功能。
i、为序列化数据使用nano protobufs
nano protobufs,语言无关,平台无关。类xml,但比xml更轻量、快速、简单。应在客户端中总是使用nano protobufs序列化数据。
j、避免使用依赖注入框架
会增大内存使用量。
k、谨慎使用外部库
l、优化整体性能
阅读Best Practice for Performance、optimizing UI、关注lint工具的建议
m、使用ProGuard来剔除不需要的代码
可以压缩、和混淆代码
n、对最终apk使用zipalign
o、使用多进程
当app在后台运行与前台一样大量的任务时,可考虑使用。比如,长时间后台播放的Music Player,若在一个进程,后台播放时,前台的UI资源无法释放。
3、内存泄漏
a、查看内存
- Android Studio自带的Memory Monitor
- DDMS的Heap
b、内存泄漏检测–LeakCanary
4、性能优化
1)过度绘制
- Overdraw屏幕上某个像素在同一帧的时间被绘制了多次
- 检测过度绘制,开启开发者选项的Debug GPU Overdraw
- 无色
- 蓝色:过度绘制1次
- 绿色:过度绘制2次
- 浅红色:过度绘制3次
- 深红色:过度绘制4次
- 最小化过度绘制:对于自定义的复杂View,可以使用clipRect函数定义绘制区域的边界。
2)Android图形渲染
有三个阶段:
- 测量
- 布局
- 绘制
每个View都要向它的父View提供自己的尺寸,如果父View发现任意的一个尺寸问题,会强制所有子View重新测量
即使没有错误发生也会发生重测:
- Relativelayout会对子视图测量两次
- 子视图使用了layout_weight属性的LinearLayout也会对子视图进行两次测量。
a、使用Hierarchy Viewer
只能与正在运行得App交互而不是源代码,可视化视图树。
b、节点性能分析
Hierachy Viewer可以显示View渲染的时间
3)数据采集和分析工具–TraceView
查看函数执行的时间,TraceView主要是用来分析数据,数据采集要调用Debug类