Android 性能优化之布局优化

Android 性能优化之布局

1.避免过度OverDraw

Overdraw就是过度绘制,是指在一帧的时间内(16.67ms)像素被绘制了多次,理论上一个像素每次只绘制一次是最优的,但是由于重叠的布局导致一些像素会被多次绘制,而每次绘制都会对应到CPU的一组绘图命令和GPU的一些操作,当这个操作耗时超过16.67ms时,就会出现掉帧现象,也就是我们所说的卡顿,所以对重叠不可见元素的重复绘制会产生额外的开销,需要尽量减少Overdraw的发生。

ndroid提供了测量Overdraw的选项,在开发者选项-调试GPU过度绘制(Show GPU Overdraw),打开选项就可以看到当前页面Overdraw的状态,就可以观察屏幕的绘制状态。该工具会使用三种不同的颜色绘制屏幕,来指示overdraw发生在哪里以及程度如何,其中:
没有颜色: 意味着没有overdraw。像素只画了一次。
蓝色: 意味着overdraw 1倍。像素绘制了两次。大片的蓝色还是可以接受的(若整个窗口是蓝色的,可以摆脱一层)。
绿色: 意味着overdraw 2倍。像素绘制了三次。中等大小的绿色区域是可以接受的但你应该尝试优化、减少它们。
浅红: 意味着overdraw 3倍。像素绘制了四次,小范围可以接受。
暗红: 意味着overdraw 4倍。像素绘制了五次或者更多。这是错误的,要修复它们。

这里写图片描述

  1. 优化布局层级

    1. 在Android中,系统会对View 进行测量、布局、和绘制时,都是对View数的遍历来进行操作的。如果view树的高度太高,就会严重影响测量、布局和绘制的速度。因此优化布局的第一个方法就是降低View树的高度.并且Google也在其API中建议View树的高度不宜超过10层。
    2. Android提供的Layout控件主要包括LinearLayout、TableLayout、FrameLayout、RelativeLayout。每个控件都有优势,尺有所短寸有所长,对于LinearLayout而言只能控制竖直方向或者横向的布局,而RelativeLayout几乎可以用于描述任意复杂度的界面。所以在表达复杂页面的时候建议用RelativeLayout,其原因是通过扁平的RelativeLayout
      来降低LinearLayout嵌套所产生布局树的高度,从而提高UI渲染的效率。

    -

  2. 避免嵌套过多无用的布局
    例如:布局文件中只有一个Button 但是它的父布局有三个LinearLayout。其中俩个LinearLayout都是可以去掉的。

    • 使用 include 标签重用Layout
      • 在开发的时候很多界面风格是都是统一的,这样就产生了一些共通的UI。比如Toolbar、Bottombar等。对于这些共通的UI,如果在每个界面中都来复制一段这样的代码,不仅不利于后期的维护,更增加了程序的冗余度。可以使用include标签来定义一个共通的UI。
<android.support.v7.widget.Toolbar
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:textSize="30sp"      
        android:gravity="center"
      />
  • 继续

    • 代码中只有一个TextView,并且居中显示了一段文字,但更多的时候我们需要通过相应的Layout组件将若干的控件组成一个共通的UI,在这里暂且把它作为一个共通UI。在代码中宽度和高度都设置为0dp,这样就迫使开发者在使用时对高度宽度进行赋值,否则将无法看见这个界面。
    • 那么怎么用include应用呢
<include layout="@layout/common_on"
android:layout_width="match_parent"
android:layout_height="match_parent/>

3.使用 ViewSub实现View 的延迟加载
除了把一个View作为共通UI,并通过include标签来进行应用之外,还可以使用ViewSub标签来实现对一个view引用并实现延迟加载。ViewSub是一个非常轻量级的组件,它不仅不可视,而且大小为0。
使用ViewSub来引用TextView

<TextView
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:id="@+id/tv"
        android:textSize="30sp"      
        android:gravity="center"
      />

<ViewSub
    android:id="@+id/not_often_use"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout="@layout/not_often_use"
    android:text="没出来"
    />

运行后发现没有显示出来,那么如何让它显示出来呢?

  • 首先通过普通的findViewById()方法找到ViewSub组件,这点与一般的组件基本相同,代码如下所示.

mViewSub=(ViewSub) findViewById(R.id.not_often_use);

接下来,有俩个方法来重新显示这个View

  • VISIBLE

    • 通过点用ViewSbu的setVisibility()来显示这个View,代码如下所示
    • mViewStub.setVisibility(View.VISIBLE);
  • inflate

  • 通过调用ViewSub的inflate()方法来显示这个view,如代码所示
    -View inflateView=mViewSub.inflate();
    这俩种方式都可以让ViewSub重新展开,显示引用的布局,而唯一不同的是inflate()方法可以返回引用的布局,从而可以在通过View.findViewById()方法来找到对应的控件,代码如下:
View inflateView=mViewSub.inflate();
TextView textView=(TextView)infateView.findViewById(R.id.tv);
textView.setText("Haha!");
  • 而不管使用那种方式,一旦ViewSub被设置为可见或是被inflate了,ViewSub就不存在了,取而代之的是被inflate的Layout,并将这个Layout的id重新设置为ViewSub中通过android:inflatedId属性所指定的ID,这也是为什么俩次调用inflate方法汇报错的原因。
  • 看到这里也许你会问这个ViewSub标签与View.GONE这个方式来隐藏一个View有什么区别呢?的确,它们的共同点都是初始化的时候不显示,但是ViewSub标签智慧在显示时,才去渲染整个布局,而View.GONE,在初始化布局树的时候就已经天假在布局树上了,相比之下ViewSub更有效率。

  • Hierarchy Viewer
    布局优化器,Hierarchy Viewer无法在真机上进行使用,它只能在工厂的demo机和模拟器上使用,即非加密过的设备。Google的“大神”——Romain Guy提供了一个开源项目View Server,通过这个程序可以让普通的手机也能使用Hierarchy Viewer,有兴趣的朋友可以去了解一下。

    https://github.com/romainguy/ViewServer

下面在模拟器上使用这个工具,它位于/sdk/tools 目录下。在命令行输入hierarchyviewer.bat启动程序。

启动虚拟机之后,运行hierarchyviewer.bat 如图

这里写图片描述

view 的树形结构图就出来了。上面有测量、布局、draw所需要的时间,可以看出那个view渲染出来慢,还有就是它用绿色、红色、黄色代表渲染速度。红色最慢,黄色次之,绿色最好。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值