问题的暴露与探索
使用universal图片库过程中发生了页面掉帧
1. 迁移的图片库的用法导致问题,根据uc侧图片库用法进行了对图片适配器做了修改。
2. 容器问题:
2.1 单独使用原生RecyclerView的页面
2.2 使用原生ImageView的页面
2.3 使用原生RecyclerView、ImageView页面
2.4 使用原生ListView的页面
...
3. 内存问题,利用安卓调试工具查看内存,发现内存没有明显异常
4. cpu问题,利用安卓调试工具查看,cpu也无明显繁忙
5. 过度绘制
6. TraceView最后才找到了硬件加速这个大boss
同一页面在不同情况下滑动中的屏幕刷新
在demoA(不同环境下)轻微滑动test3测试页面
在demoB中轻微滑动test3测试页面
对比图
发现在每隔16ms的屏幕刷新中,掉帧的场景中走了drawSoftware,而不是draw方法,下边是ViewRootImpl在屏幕刷新时的源码:
注释部分表示,如果硬件加速不可用情况下,会尝试用软件加速方式进行刷新。所以推断demoA页面应该没有开启硬件加速。在demoB中关闭默认的硬件加速,复现了demoA的掉帧。打开硬件加速后,demoA页面无异常。
硬件加速VS软件加速
硬件加速,直观上说就是依赖GPU实现图形绘制加速,同软硬件加速的区别主要是图形的绘制究竟是GPU来处理还是CPU,如果是GPU,就认为是硬件加速绘制,反之,软件绘制。在Android中也是如此,不过相对于普通的软件绘制,硬件加速还做了其他方面优化,不仅仅限定在绘制方面,绘制之前,在如何构建绘制区域上,硬件加速也做出了很大优化,因此硬件加速特性可以从下面两部分来分析:
1、前期策略:如何构建需要绘制的区域
2、后期绘制:单独渲染线程,依赖GPU进行绘制
无论是软件绘制还是硬件加速,绘制内存的分配都是类似的,都是需要请求SurfaceFlinger服务分配一块内存,只不过硬件加速有可能从FrameBuffer硬件缓冲区直接分配内存(SurfaceFlinger一直这么干的),两者的绘制都是在APP端,绘制完成之后同样需要通知SurfaceFlinger进行合成,在这个流程上没有任何区别,真正的区别在于在APP端如何完成UI数据绘制,
作者:看书的小蜗牛
链接:https://juejin.im/post/5a1f7b3e6fb9a0451b0451bb
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
开启硬件加速
- 应用层
<application
android:hardwareAccelerated="true">
</application>
- Activity层
<activity
android:hardwareAccelerated="true">
</activity>
- Window层级
getWindow().setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
- View层级
view.setLayerType(View.LAYER_TYPE_HARDWARE, null);