美文网首页
渲染优化

渲染优化

作者: 最美下雨天 | 来源:发表于2018-07-09 15:28 被阅读13次

    文章来源:
    http://wuxiaolong.me/2017/03/26/Rendering/
    https://www.jianshu.com/p/989ce9eb7af8
    hz:每秒刷新的次数

    著名的“16ms”原则:
    我们通常都会提到60fps(Frame Per Second)与16ms,可是知道为何会是以程序是否达到60fps来作为App性能的衡量标准吗?
    60fps:人眼与大脑之间的协作无法感知超过60fps的画面更新。
    *16ms:因为Android设定的刷新率是60fps,也就是每秒60帧,即16ms=1000/60Hz
    Android系统每隔16ms会发出VSYNC信号重绘我们的界面。
    

    就像这样:


    image.png

    如果你的某个操作花费时间是24ms,系统在得到VSYNC信号的时候就无法进行正常渲染,这样就发生了丢帧现象。那么用户在32ms内看到的会是同一帧画面。


    image.png
    Overdraw(过度绘制)是指系统在单个渲染帧中多次绘制屏幕上的像素。例如,如果我们有一堆堆叠的UI卡,不可见的UI也在做绘制的操作,这样会浪费大量的CPU和GPU资源。
    渲染操作通常依赖于两个核心组件:CPU与GPU。CPU负责包括Measure,Layout,Record,Execute的计算操作,GPU负责Rasterization(栅格化)操作

    如何检测?

    • Show GPU Overdraw
      设置 -> 开发者选项 -> 调试GPU过度绘制 ->显示过度绘制区域。
      对比一张Overdraw的参考图,分别有蓝色,淡绿,淡红,深红代表了4种不同程度的Overdraw情况:


      image.png

      蓝色,淡绿,淡红,深红代表了4种不同程度的Overdraw情况,我们的目标就是尽量减少红色Overdraw,看到更多的蓝色区域。

    Overdraw有时候是因为你的UI布局存在大量重叠的部分,还有的时候是因为非必须的重叠背景。例如某个Activity有一个背景,然后里面的Layout又有自己的背景,同时子View又分别有自己的背景。仅仅是通过移除非必须的背景图片,这就能够减少大量的红色Overdraw区域,增加蓝色区域的占比。这一措施能够显著提升程序性能。

    • Profile GPU Rendering
      打开Profile GPU Rendering,显示每帧画面所需要渲染的时间。
      设置 -> 开发者选项 -> GPU呈现模式分析 -> 在屏幕上显示为条形图
    image.png

    界面上会滚动显示垂直的柱状图来表示每帧画面所需要渲染的时间,柱状图越高表示花费的渲染时间越长。中间有一根绿色的横线,代表16ms,我们需要确保每一帧花费的总时间都低于这条横线,这样才能够避免出现卡顿的问题。

    • Hierarchy Viewer
      用Hierarchy Viewer工具检查Activity中的布局是否过于复杂
      Tools -> Android -> Android Device Monitor。


      image.png
      image.png
    image.png

    其实中带有红色或黄色的点代表速度较慢的View。

    优化方案:

    • 删除布局中不必要的背景属性
    • 尽量减少布局的层级
      来源:https://blog.csdn.net/xyz_lmn/article/details/14524567
      减少视图层级<merge />
      <merge/>标签在UI的结构优化中起着非常重要的作用,它可以删减多余的层级,优化UI。<merge/>多用于替换FrameLayout或者当一个布局包含另一个时,<merge/>标签消除视图层次结构中多余的视图组。例如你的主布局文件是垂直布局,引入了一个垂直布局的include,这是如果include布局使用的LinearLayout就没意义了,使用的话反而减慢你的UI表现。这时可以使用<merge/>标签优化。
    <merge xmlns:android="http://schemas.android.com/apk/res/android">
     
        <Button
            android:layout_width="fill_parent" 
            android:layout_height="wrap_content"
            android:text="@string/add"/>
     
        <Button
            android:layout_width="fill_parent" 
            android:layout_height="wrap_content"
            android:text="@string/delete"/>
     
    </merge>
    

    现在,当你添加该布局文件时(使用<include />标签),系统忽略<merge />节点并且直接添加两个Button。

    • 需要时使用<ViewStub />
      <ViewStub />标签最大的优点是当你需要时才会加载,使用他并不会影响UI初始化时的性能。各种不常用的布局想进度条、显示错误消息等可以使用<ViewStub />标签,以减少内存使用量,加快渲染速度。<ViewStub />是一个不可见的,大小为0的View。<ViewStub />标签使用如下:
    
    <ViewStub
        android:id="@+id/stub_import"
        android:inflatedId="@+id/panel_import"
        android:layout="@layout/progress_overlay"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom" />
    

    当你想加载布局时,可以使用下面其中一种方法:

    
    ((ViewStub) findViewById(R.id.stub_import)).setVisibility(View.VISIBLE);
    // or
    View importPanel = ((ViewStub) findViewById(R.id.stub_import)).inflate();
    
    

    当调用inflate()函数的时候,ViewStub被引用的资源替代,并且返回引用的view。 这样程序可以直接得到引用的view而不用再次调用函数findViewById()来查找了。
    注:ViewStub目前有个缺陷就是还不支持 <merge /> 标签。

    相关文章

      网友评论

          本文标题:渲染优化

          本文链接:https://www.haomeiwen.com/subject/tuzzuftx.html