目录
文章会依照如下目录来整理优化点,也算是给自己挖个坑,以后有新的优化点会逐步补充进来,持续更新,也欢迎大家查漏补缺(´・ω・`)
- 启动加速
- 内存相关
- 渲染相关
- 编码相关
- 非性能优化点
- 性能调试工具篇
启动加速
Splash页面
从应用启动到完全渲染出第一个页面,中间的加载时间应用会呈现白屏或黑屏状态,Material Design设计规范建议我们应该给这段时间设置一张闪屏图(即占位图),让用户感到整个启动过程“毫无违和感”
写一个有闪屏图作为背景主题
创建一个专门用于显示启动页的SplashActivity设置该主题
初始化组件及三方库
在Application
的onCreate
方法中我们通常会做一些基础组件或第三方库的初始化工作,过于繁重的加载任务会影响应用从启动到显示MainActivity
的间隔时间,所以应该遵循如下原则:
异步加载
可以在子线程中初始化的任务放到子线程中完成(new Thread
或IntentService
)延迟加载
不可以在子线程中初始化,但不需要启动后立刻使用的库可以在MainActivity
渲染完成后再加载,或给一个固定时间延迟加载懒加载
顾名思义,需要使用时才加载,不使用则不加载常规加载
如果必须在主线程中加载且要启动后需要立即生效的库,则在Application
的onCreate
方法中加载
异步加载
|
|
延迟加载
内存相关
Bitmap不再使用时没有及时
recycler()
导致的泄漏,关于这点可以用LruCache
来辅助管理Bitmap
,具体如何操作在以前的一篇文章ECardFlow踩坑记的最后有提及,这里就不赘述了,为了防止加载大量Bitmap导致的OOM,还要注意对Bitmap的inSampleSize
缩放比例和decodeformat
解码格式做调整1234567891011121314BitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = true;BitmapFactory.decodeResource(mContext.getResources(), mRes[position], options);int inSampleSize = Math.min(options.outWidth / width, options.outHeight / height);int dstSample = 1;if (inSampleSize > dstSample) {dstSample = inSampleSize;}options.inJustDecodeBounds = false;//根据实际需要的图片大小来加载,当原图过大时会按比例缩放,而不是直接加载原图浪费内存空间options.inSampleSize = dstSample;//RGB_565、ARGB_4444等略微牺牲一些清晰度比ARGB_8888占用更少的空间options.inPreferredConfig = Bitmap.Config.RGB_565;return BitmapFactory.decodeResource(mContext.getResources(), mRes[position], options);某些场景考虑使用
applicationContext
代替activityContext
,尤其是将引用传入单例\静态对象时,防止Activity
被持有引用无法回收- 善用
软引用
,弱引用
,一句话概括四种引用的话:强引用
,JVM宁可OOM也不会主动回收的引用软引用SoftReference<T>
,内存不足时才回收的引用弱引用WeakReference<T>
,GC时只要发现了就会被回收的引用虚引用PhantomReference<T>
,形同虚设,随时可能被回收的引用
非静态内部类或匿名类会默认持有外部类的引用,和外部类无关时应该定义成
static
静态内部类,如下使用Static + WeakReference
的方式来达到断开Handler与Activity之间存在引用关系123456789101112131415161718private static class MyHandler extends Handler {WeakReference<ECardFlowLayout> mLayout;MyHandler(ECardFlowLayout layout) {mLayout = new WeakReference<>(layout);}public void handleMessage(Message msg) {ECardFlowLayout layout = mLayout.get();switch (msg.what) {case MSG_JUDGE_RESET:layout.judgeReset();break;}}}部分Android系统自带的服务类在注册使用完毕后需要反注册
unregister()
,Java文件流等资源型对象使用完毕后应该关闭close()
- 单例对象往往是静态的,若向其中注册监听
addListener
传入对象,需要在使用结束后清除监听置null
,防止持续持有引用 - 及时清理集合类中不再使用的引用,否则集合会越来越大,如果集合是static的话会更严重
- 部分第三方库为避免泄漏会提供类似
Destroy()
,Recycler()
方法,注意调用
渲染相关
- 使用
include
标签复用布局,提高代码可读性 - 使用
merge
标签合并最外层根布局,减少一层层级,通常配合include
或自定义ViewGroup
或布局顶点是FrameLayout
且不需要设置background或padding等属性的场景 - 使用
ViewStub
标签,在该视图需要加载时才加载,比渲染后再View.GONE
更好 - 当需要空视图填充空间时用
<Space>
比<View>
更合适 RelativeLayout
中子View的onMeasuer
会执行两次,LinearLayout
使用weight
属性时也是,所以优先使用LinearLayout
和FrameLayout
完成布局,避免RelativeLayout
层层嵌套TextView
的drawableLeft
等属性可以替代TextView
+ImageView
的组合TextView
使用\n
换行,android:lineSpacingMultiplier
控制行间距,SpannableString
做文字图片混编或局部文字大小、颜色、点击事件等等的控制可以满足大多数场景,而不是使用多个TextView
- 在合适的场景下尝试使用体积很小的
WebP格式
,支持拉伸的.9图
,SVG矢量图
及其动画 - 包含大量绘制的复杂动画使用
SurfaceView
或TextureView
来完成 - 无交互、纯展示的自定义控件效果,用自定义
Drawable
比自定义View
更高效 - 应用运行后打开手机设置中的
gpu呈现模式分析
,出现红色的地方说明发生了多层过度绘制
,举个栗子即父布局设置了背景颜色,子布局及其子布局又设置了背景颜色,在同一片区域做了多次重复渲染,这时候就需要去排查问题了
编码相关
- 使用在内存层面做过优化的
ArrayMap/SparseArray
代替HashMap
- 避免在Android里面使用
Enum
,开销是final static
的数倍 - 大量字符串拼接时使用
StringBuilder
代替String
,并发场景下使用StringBuffer
- 使用基本类型时注意避免无意义的装箱拆箱
- 善用经典算法,如
快排法
,二分法
等,减少时间复杂度 - 反射
Reflect
只是黑科技,会增加性能负担,避免大量使用
其他非性能优化点
除了最直观的性能优化外,还有一些优化点也可以提升用户体验
- APK安装包瘦身(方便下载或更新)
- 电量优化(省电)
- 网络流量优化(省流量)
- 弱网络状态优化(渣网也能玩的溜)
- 离线缓存优化(没网也能玩的溜)
工具篇
本篇只列举工具,起个索引作用,每种调试工具的具体用法已经有很多优秀的文章介绍过了,可以参考附上的链接
0. LeakCanary
Square公司开源的内存泄漏检测库,发生泄漏时会记录下泄漏的调用堆栈,可以非常方便的定位泄漏点
开源地址:LeakCanary
1. Strictmode
Android自带,可以在代码中开启,严格模式下规范了开发者的行为,若写出了违反严格策略的代码会给予警告
参考链接:StrickMode严苛模式检测耗时与内存问题
2. Lint
Android Studio自带,lint是多功能的静态检测扫描工具,可以发现的问题包括:
- 缺少翻译的文本
- 布局性能(无意义的嵌套等)
- 未使用到的资源(代码、图片等)
- 不一致的数组大小
- 硬编码
- 图标问题(缺少、重复、错误等问题)
- 可用性问题(如未指定的文本字段的输入类型)
- manifest文件的错误
参考链接:Android代码优化——使用Android lint工具
3. TraceView、Systrace
Android自带,可以方便的查看各线程的执行情况,以及采集CPU数据等等,最常用于追踪每个方法的执行时间,定位耗时点,进而优化
参考链接:TraceView 分析图怎么看
4. HierarchyViewer
SDK自带,可查看布局层次结构,View绘制时耗时
参考链接:Android UI 优化——使用HierarchyViewer工具
5. Allaction Tracing
DDMS自带,执行某步操作后,详细的看到内存发生的变化
参考链接:Allaction Tracing追踪内存分配的轨迹
OK收工~ 滚去睡觉。。(= ̄ω ̄=)
参考文章
性能调优・技术优化点
Android性能优化的方方面面
App性能优化系列结语篇
Android内存优化之OOM
声明:本站所有文章均为原创或翻译,遵循署名-非商业性使用-禁止演绎 4.0 国际许可协议,如需转载请确保您对该协议有足够了解,并附上作者名(Est)及原贴地址