1、Android绘制显示原理
Android应用程序把经过测量(measure)、布局(layout)、绘制(draw)的数据发送系统服务,surfaceFinger通过显示刷新机制渲染到屏幕上。
Android的显示刷新机制是一秒钟60帧,即16ms刷新一次,如果16ms未能完成渲染,则会发生丢帧,导致页面卡顿。
2、页面卡顿原因
- 绘制任务太重,16ms未能完成绘制
- 主线程执行耗时操作,当系统要刷新时,主线程没能准备好绘制数据
- 频繁GC,停止工作线程,导致页面卡顿
3、优化策略
- 避免在主线程进行耗时操作,例如请求网络、IO读取数据
- 避免过度绘制,设置——开发者——GPU过度绘制,去除多余背景,getWindow().setBackgroundDrawable(null)。
- 布局优化:
(1)不影响层级深度的情况下,使用LinearLayout和FrameLayout而不是RelativeLayout。RelativeLayout测量时对子布局的水平和竖直方向调用2次。
(2) 使用<include>复用布局(例如标题栏),<merge>减少布局层次,LayoutInflater遇见<merge>标签只会把解析子View,把加到<merge>的父View中,不会增加布局层次,配合<incldue>使用。
https://blog.csdn.net/a740169405/article/details/50473909
(3)<ViewStub>
ViewStub是view的子类,测试时设置宽高为0,并且不绘制,同时设置自身不可见(Gone),达到延迟加载的目的。
https://blog.csdn.net/a740169405/article/details/50351013
4、检测卡顿
- 对主线程Looper.loop中的msg.target.dispatchMessage(msg)方法的耗时进行检测,源码中执行前后有日志打出,通过过滤日志能知道耗时。
- Andriod系统中每16ms发出信号刷新屏幕,SDK中有相关的类和回调,检测2次刷新的间隔时间,大于16ms则打印出堆栈信息定位问题。
https://blog.csdn.net/lmj623565791/article/details/58626355
https://blog.csdn.net/u013493809/article/details/62215250 - TraceView
使用的思路分析:
(1)调用次数不多,但每次耗时长的方法
(2)自身耗时不长,但频繁调用的方法
关于第一种,通常做法是先按Cpu Time/Call降序排序,然后看Incl Cpu Time的大小,综合起来越大的性能问题越严重
关于第二种,通常做法是按Calls + Recur Calls/Total降序排序,然后看Incl Cpu Time的大小,综合起来越大的性能问题越严重
https://blog.csdn.net/qianrushi9/article/details/58605827
参考资料
https://www.jianshu.com/p/9755da0f4e8f
https://www.jianshu.com/p/307ba8911799
https://blog.csdn.net/lmj623565791/article/details/45556391/