Android中布局的优化

个人掘金地址android

#本文涉及到的知识点bash

  • 简单的说明如下布局优化的重要性
  • 一些布局使用的注意事项
  • include、merge与ViewStub的使用
  • ConstraintLayout的使用

##1.布局优化的重要性工具

在平常开发中对于布局咱们不多注重性能,主要注重的就是相应的展现问题。可能因为界面的复杂程度,使得界面嵌套的层级过多,这样也就致使了绘制页面的卡顿现象。增长了GPU渲染的复杂程度。这里引用一张图片来讲明相应的问题。布局

GPU过分绘制参考图

怎么查看呢?手机设置->开发者选项->调试GPU过分渲染 打开以后你就能看到你的APP到底有没有过分绘制了。若是你看见的是一片红,那么恭喜你...你必须考虑相应的优化了!说了这么多,其实最重要的就是减小层级、减小相应的过分绘制,就能有效的对布局进行相应的优化。因此在Android作一些简单的布局优化仍是有必要的。。。性能

##2.一些布局使用的注意事项flex

这里先提出个问题,你们想一下?若是项目中有这样一个需求,竖直排列两行每行两个元素,你们怎么去实现呢?相信有的人会使用相对布局,有的人会使用线性布局,那么问题就来了,若是你使用线性布局的话,就会存在布局嵌套的问题,就平白的多了一层布局嵌套,平时开发的时候这样的问题不少,若是你多加注意的话,你会发现不少这样的问题。优化

这里我主要想说的是,若是在平时开发布局的时候,若是在布局不是很复杂的状况下尽可能使用相对布局,少用线性布局。可是你们要注意一点,若是布局复杂的话,或者层级较深的状况下,最好仍是使用线性布局。这里不知道你们注意没有,在Android Studio2.+版本的时候,全部默认的布局都是线性布局,为何呢?我就不在继续深刻讲解了,感兴趣的同窗能够看看尹star 的->Android中RelativeLayout和LinearLayout性能分析主要是Measure在测量的时候产生的性能消耗!因此这个问题主要看你布局是否比较复杂。。。其实在如今的版本中,google推荐咱们使用的是ConstraintLayout(这个我会在后面详细的讲解)google

##3.include、merge与ViewStub的使用spa

说到布局优化问题,很难不说起include、merge与ViewStub的使用,可是这些都有相对的局限性的,下面咱们就来一一讲解:调试

###3.1 include的使用和注意事项

这个东西相信你们都不陌生,它能帮咱们解决布局复用的问题,只要include导入一个布局就能够了。像这样:

<include layout="@layout/XXX"/>
复制代码

XXX表明引入的布局。是否是很简单,那么我问你们几个问题?

  • 若是在include标签中我设置相应的layoutxxx的属性,会对原来的布局有什么影响?
  • 若是在include标签中我设置了id,会对原来的布局有什么影响?

这些问题,相信细心的人应该会有体会的,可是对于有些人来讲,或许很陌生。因此这里有必要说明一下:

  • 当你在include中设置layoutxxx属性的时候,会覆盖相应导入根布局的layoutxxx属性,怎么理解呢?也就是说若是你导入的布局是这样的
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#223344"
        android:gravity="center"
        android:text="导入的布局"
        android:textColor="@android:color/white"
        android:textSize="20sp" />

</LinearLayout>
复制代码

这里看好,LinearLayout的宽和高是占用父窗体。若是你要是这么写

<include layout="@layout/test_view" />
复制代码

的话,会显示全屏的,就像这个样子

没有设置layoutxxx的属性

可是若是你要是写成这个样子就不同了

<include
        layout="@layout/test_view"
        android:layout_width="200dp"
        android:layout_height="200dp" />
复制代码

会变成这个样子

设置了layoutxxx的属性

这里要特别注意一下。。。

  • 当你在include中设置id的时候,会覆盖相应导入根布局的id属性,也就是说你只能使用include中的id属性获取根view了!

###3.2 merge的使用和注意事项

对于新手来讲,这个标签应该不多使用,至少我是这样的,其实我呆了这么多公司,也不多有人去用这个,可能我呆的都是小公司吧!哈哈。。。不闲扯了,其实这个标签主要是针对include导入的标签的根布局来讲的,能够减小一个层级的嵌套!

先来讲一下这个怎么看啊!!!不说这个的都是扯淡。。。在Android Studio3.+版本上按照下图获取!

查看视图树的工具

中间会弹出一个对话框,而后你就点肯定,就能查看相应的视图树了。。。

  • 当你没有使用merge标签的时候,布局是这个样子的!
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#223344"
        android:gravity="center"
        android:text="导入的布局"
        android:textColor="@android:color/white"
        android:textSize="20sp" />

</LinearLayout>
复制代码

这个时候你查看一下视图树你会发现会出现下面这个样子。

未使用merge标签的视图层级

我已经用红框画出来了,中间有一层LinearLayout做为根布局,可是若是你把上面的LinearLayout换成merge标签就不会有中间这层LinearLayout了。这个就不贴图了,不信的你能够试试。。。

还有一个问题须要注意: 这里有必要说明一下,若是你要给merge标签设置一些属性怎么办?实际上是这样的,你能够根据include的父控件进行属性的设置,若是父控件是LinearLayout你就能够设置weidge或者相应LinearLayout的特有属性...这也充分说明了为何include可使用layoutxxx属性覆盖根布局的layoutxxx属性。

###3.3 ViewStub的使用和注意事项

其实关于这个ViewStub这个标签,就至关于延时加载,可是有不少局限性,打个比方说吧!相应在平时开发的时候,都会根据状态进行一些控件的显示和隐藏吧,通常的处理都是View的setVisibility();可是这里若是你改变一次以后还能进行改变的话,那么就不能使用ViewStub这个标签。由于ViewStub对控件只有一次的改变,其实ViewStub在布局加载的时候已经加载出来了,只是宽和高都是0罢了,当你inflate()的时候,再去加载这个总体的View,达到了延迟加载的目的!

基本的写法就是这样,也是导入一个layout

<ViewStub
        android:id="@+id/vs_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout="@layout/test_view" />
复制代码

何时你想加载了,就调用View inflate = mVs.inflate();方法就能让这个View显示出来,可是必定要注意,这个方法只能使用一次,切记!切记!切记!重要的事情说三遍,当这个View加载出来的时候,你就能够像对待其余View对待它了,若是你要对这个View作一些特有控件的操做,最好强转一下。。。

基本上上面这三个View优化的标签我总结的就这么多,有什么不对的还请指出,我会当即改正的!!!

##4. ConstraintLayout的使用

关于这个控件,其实google早在很早的时候就让咱们去尝试着使用了,可是在1.0.2那个版本的时候(记不太清楚了)才做为根布局使用的。

A ConstraintLayout is a ViewGroup which allows you to position and size widgets in a flexible way. Note: ConstraintLayout is available as a support library that you can use on Android systems starting with API level 9 (Gingerbread). As such, we are planning on enriching its API and capabilities over time. This documentation will reflect those changes.

这里面引用了google的解释,大概的意思是

ConstraintLayout继承ViewGroup容许您以灵活的方式定位和调整小部件的大小。 ConstraintLayout可用做支持库,您能够从API级别9(姜饼)开始在Android系统上使用该支持库。所以,咱们计划在一段时间内丰富其API和功能。本文档将反映这些更改。

主要是约束内部控件位置的布局,里面包含关于相对位置的属性:

  • layout_constraintLeft_toLeftOf 当前控件的左侧和目标控件的左侧对齐
  • layout_constraintLeft_toRightOf 当前控件的左侧和目标控件的右侧对齐
  • layout_constraintRight_toLeftOf
  • layout_constraintRight_toRightOf
  • layout_constraintTop_toTopOf
  • layout_constraintTop_toBottomOf
  • layout_constraintBottom_toTopOf
  • layout_constraintBottom_toBottomOf
  • layout_constraintStart_toEndOf
  • layout_constraintStart_toStartOf
  • layout_constraintEnd_toStartOf
  • layout_constraintEnd_toEndOf

其实属性不少,估计让你记你也记不住,因此总结一下:

这里全部的均可以这么去理解,layout_xxxA_toxxxB 理解为,当前控件的A侧和目标控件的B侧对齐,你可能仍是不理解,拿第一个举例说明下,就是当前控件的左侧和目标控件的左侧对齐,标记了两个,其余的以此类推。这里注意里面设置的参数是目标控件的id/父容器只有这两种可能! 若是你有两个控件,左侧的以父控件对齐,另外一个控件以左侧的控件对齐,这时候若是右侧以父控件对齐的话,这个控件会在右侧剩下的空间居中(像下面这样),可是若是你要是不设置右侧的属性的话,那么两个会挨着!(是那个属性拆散了它们!哈哈)

  • layout_constraintHorizontal_bias 水平误差百分比
  • layout_constraintVertical_bias 竖直误差的百分比

这两个属性是针对于上面这个产生误差的(只能设置觉得小数,最大是1),其实我试过,只要你左右或者上下都有约束的时候,这个相应的属性才生效,不然是无效的(如:一个控件左右都有约束,那么设置layout_constraintHorizontal_bias才会生效,不然是不会生效的,竖直方向的同理)

  • android:layout_marginStart
  • android:layout_marginEnd
  • android:layout_marginLeft
  • android:layout_marginTop
  • android:layout_marginRight
  • android:layout_marginBottom

若是你设置了相应的margin_xxx属性,那么主要是产生了相应的边距,和其余的控件都同样,这里就再也不多作解释了.

  • layout_goneMarginStart
  • layout_goneMarginEnd
  • layout_goneMarginLeft
  • layout_goneMarginTop
  • layout_goneMarginRight
  • layout_goneMarginBottom

这里说明一个问题,当你有一个View处于GONE的状况,其余View还以来这个View来进行布局,那么就须要设置上面的goneMarginXXX来设置相应的Margin**(PS:这个只有在你依赖的那个约束为GONE的时候才会生效的属性)**

  • android:minWidth 设置布局的最小宽度
  • android:minHeight 设置布局的最小高度
  • android:maxWidth 设置布局的最大宽度
  • android:maxHeight 设置布局的最大高度

这几个属性没有什么好说的了!

  • layout_constraintDimensionRatio 设置宽高比

这个属性颇有意思:设置相应的宽高比,可是我试了,至少要有三面有约束,不然不起做用,而且宽度和高度都应该设置成"0",参数值能够是"1:1"或者"h,1:1"也能够是"w,1:1"其中h表明限制高度,w表明限制宽度.这里的比例无论你前面是什么,后面的比值都是"宽度:高度"

  • layout_constraintHorizontal_weight
  • layout_constraintVertical_weight

这两个属性至关于LinearLayout的weight属性和LinearLayout的属性设置是同样的

  • layout_constraintHorizontal_chainStyle
  • layout_constraintVertical_chainStyle
    • CHAIN_SPREAD 默认样式(若是某些小部件设置为MATCH_CONSTRAINT,则它们将拆分可用空间)
    • CHAIN_SPREAD_INSIDE 但链条的终点不会被分散
    • CHAIN_PACKED 链条的元素将被打包在一块儿。

样式说明

这里我用的时候踩了一个大坑,这里所谓的链式,你必须确保从左至右或者从上至下多有的约束都连着,这里的连着是都有相应的约束: 如view a 和view b在竖直方向上造成锁链:a的属性设置为 top_toTopOf = “parent” bottom_toTopOf = “b” b的属性设置为top_toBottomOf=“a” bottom_toBottom = “parent"切记!切记!切记!都要连上....重要的事情说三遍,不然你是看不见效果的.效果就是上面这张图的效果!

这里使用了这个布局,就能减小布局的嵌套,也使得绘制的时候能减小GPU的负担,这样就能达到布局优化的目的了!!!

上面这些......基本上就是我在项目中优化布局时候所作的一些优化,有什么不妥的地方还请指正!


欢迎关注个人公众号
相关文章
相关标签/搜索