前言

我们知道一个界面的测量和绘制是通过递归来完成的,减少布局的层数就会减少测量和绘制的时间,从而性能就会得到提升。当然这只是布局优化的一方面,那么如何来进行布局的分析和优化呢?本篇文章会给你一个满意的答案。

1.布局优化工具

在讲到如何去布局优化前,我们先来学习两种布局优化的工具。

1.1 Hierarchy Viewer

Hierarchy Viewer是Android SDK自带的可视化的调试工具,用来检查布局嵌套和绘制的时间。需要注意的是在在Android的官方文档中提到:出于安全考虑,Hierarchy Viewer只能连接Android开发版手机或是模拟器。
首先我们在Android Studio中选择Tools->Android->Android Device Monitor,在Android Device Monitor中选择Hierarchy Viewer ,如下图所示:


选择Hierarchy Viewer后会进出Hierarchy Viewer窗口,如下图所示。

Hierarchy Viewer中有4个四个子窗口,它们的的作用为:

  • Windows:当前设备所有界面列表。
  • Tree View:将当前Activity的所有View的层次按照高层到低层从左到右显示出来。
  • Tree Overview:全局概览,以缩略的形式显示。
  • Layout View:整体布局图,以手机屏幕上真实的位置呈现出来。单击某一个控件,会在Tree Overview窗口中显示出对应的控件。

根据上面讲到的Hierarchy Viewer的4个四个子窗口,我们可以很容易的查看我们布局控件的层级关系。当然Hierarchy Viewer还可以查看某一个View的耗时,我们可以选择某一个View,然后单击下图红色箭头标识的按钮,这里我们把他简称为Layout Time按钮。


从图中可以看出被选中的RelativeLayout自身的Measure、Layout和Draw的耗时数据都为n/a。单击Layout Time按钮后,就可以查看View的耗时情况了,如下图所示。

QQ截图20170324170337.png

从图中可以看出,被选中的LinearLayout给出了自身Measure、Layout和Draw的耗时,并且它所包含的View中都有了三个指示灯,分别代表当前View在Measure、Layout和Draw的耗时,绿色代表比其他50%View的同阶段(比如Measure阶段)速度要快,黄色则代表比其他50%View同阶段速度要慢,红色则代表比其他View同阶段都要慢,则需要注意了。如果想要看View的具体耗时,则点击该View就可以了。

1.2 Android Lint

Android lint是在ADT 16提供的新工具,它是一个代码扫描工具,通过代码静态检查来发现代码出现的潜在问题,并给出优化建议。检查的范围主要有以下几点:

  • Correctness 正确性
  • Security 安全性
  • Performance 性能
  • Usability 可用性
  • Accessibility 可达性
  • Internationalization 国际化

Android Lint功能十分强大,这里我们只关注XML布局检查,我们可以通过Android Studio的Analyze->Inspect Code来配置检查的范围,如下图所示。

点击上图的OK按钮后,就会进行代码检查,检查的结果如下图所示。

图中列出了项目中出现的问题种类,以及每个问题种类的个数,问题种类包括我们前面提到的Correctness 、Internationalization 、Performance等。我们点击展开最后的XML一项,点击一个问题,就会出现如下图的提示。

可以看出给出了Namespace declaration is never used的提示,并指出了问题所在的文件和行数,我们点击数字3,直接跳入到问题的代码,发现如下代码:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent">
...

第三行的Namespace 确实没有被用到。如果想要自定义Android Lint的检查提示,可以通过File->Settings->Editor->Inspections中来配置Android Lint,如下图所示。

从图中可以发现,我们可以配置Android Lint检查的范围以及问题的严重等级。

2.布局优化方法

布局的优化方法很多,主要包括合理运用布局、Include、Merge、ViewStub,下面我们来一一对这些内容进行讲解。

2.1 合理运用布局

我们常用的布局主要有LinearLayout、RelativeLayout和FrameLayout等,合理的使用它们可以使得Android绘制工作量变少,性能得到提高。我们来举个简单的例子。

<?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"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="布局优化" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Merge" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ViewStub" />
</LinearLayout>
</LinearLayout>

上面的代码用了两个LinearLayout来进行布局,运行效果如下图所示。


我们用Hierarchy Viewer来查看层级情况,如下图所示。

可以看到我们的布局共有3层,一共含有5个View。如果我们用RelativeLayout来进行改写呢?代码如下所示。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv_text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="布局优化" />
<TextView
android:id="@+id/tv_text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_toRightOf="@id/tv_text1"
android:text="Merge" />
<TextView
android:id="@+id/tv_text3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/tv_text2"
android:layout_marginLeft="10dp"
android:layout_toRightOf="@+id/tv_text1"
android:text="ViewStub" />
</RelativeLayout>

我们只用了一个RelativeLayout来进行布局。用Hierarchy Viewer来查看层级情况,如下图所示。

布局共有两层,一共含有4个View。从这里我们就可以看出我们用RelativeLayout减少了一层的布局,当然这只是一个简单例子,如果布局复杂,那么合理的用RelativeLayout来替代LinearLayout会减少很多层布局。
如果根据上面的例子来看,RelativeLayout的性能是比LinearLayout低,因为RelativeLayout中的View的排列方式是基于彼此依赖的。但是在实际开发中面对的情况比较多,不能轻易的说谁的性能更好。一般情况下,但是如果布局层数较多时,推荐用RelativeLayout来实现。如果布局嵌套较多,推荐使用LinearLayout来实现。

2.2 使用Include标签来进行布局复用

2.3 用Merge标签去除多余层级

Merge意味着合并,在合适的场景使用Merge标签可以减少多余的层级。Merge标签一般和Include标签搭配使用

merge标签最好是来替代FrameLayout,或者是布局方向一致的LinearLayout,比如当前父布局LinearLayout的布局方向是垂直的,包含的子布局LinearLayout的布局方向也是垂直的则可以用merge标签.

2.4 使用ViewStub来提高加载速度

一个很常见的开发场景就是我们想要一个布局时,并不是所有的控件都需要显示出来,而是显示出一部分,对于这种情况,我们一般采用的方法就是使用View的GONE和INVISIBLE,但是这种方法效率不高,虽然是达到了隐藏的目的,但是仍在布局当中,系统仍然会解析它们,我们可以用ViewStub来解决这一问题。
ViewStub是轻量级的View,不可见并且不占布局位置。当ViewStub调用inflate方法或者设置可见时,系统会加载ViewStub指定的布局,然后将这个布局添加到ViewStub中,在对ViewStub调用inflate方法或者设置可见之前,它是不占布局空间和系统资源的,它主要的目的就是为目标视图占用一个位置。因此,使用ViewStub可以提高界面初始化的性能,从而提高界面的加载速度。

我们首先在布局中加入ViewStub标签,布局代码如下所示。

<?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"
android:orientation="vertical">
<ViewStub
android:id="@+id/viewsub"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout="@layout/titlebar"/>
...
</LinearLayout> ViewStub标签中用android:layout引用了此前写好的布局titlebar.xml。这时我们运行程序,ViewStub标签所引用的布局是显示不出来的,因为引该局还没有加载到ViewStub中,接下来在代码中使用ViewStub: public class MainActivity extends AppCompatActivity {
private ViewStub viewsub;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewsub= (ViewStub) findViewById(R.id.viewsub);
// viewsub.inflate();//
viewsub.setVisibility(View.VISIBLE);//
}
} 可以使用注释1和注释2处的代码来将ViewStub引用的布局加载到ViewStub中,这样引用的布局就显示了出来。

在使用ViewStub时需要主要以下问题:

  • ViewStub只能加载一次,加载后ViewStub对象会被置为空,这样当ViewStub引用的布局被加载后,就不能用ViewStub来控制引用的布局了。因此,如果一个控件需要不断的显示和隐藏,还是要使用View的Visibility属性。
  • ViewStub不能嵌套Merge标签。
  • ViewStub操作的是布局文件,如果只是想操作具体的View,还是要使用View的Visibility属性。

3.避免GPU过度绘制

什么是过度绘制呢?我们来打个比方,假设你要粉刷房子的墙壁,一开始刷了绿色,接着又刷了黄色,这样黄色就将绿色盖住,也就说明第一次的大量粉刷工作白做了。同样手机屏幕绘制也是如此,过度绘制是指在屏幕上某个像素在同一帧的时间内被绘制多次,从而浪费了GPU和CPU的资源。产生这一原因主要有两个原因:

  • 在XML布局中,控件有重叠且都有设置背景。
  • View的OnDraw中同一区域绘制多次。

过度绘制是不可避免的,但是过多的过度绘制会浪费很多资源,并且导致性能问题,因此,避免过度绘制是十分必要的。我们可以用Android系统中自带的工具来检测过度绘制。首先要保证系统版本在Android 4.1以上,接着在开发者选项中打开调试GPU过度绘制选项就可以进入GPU过度绘制模式,如下图所示。

这时屏幕会出现出各种颜色,主要有以下几种,如下图所示。

各个颜色的定义为:

  • 原色: 没有过度绘制 – 每个像素在屏幕上绘制了一次。
  • 蓝色: 一次过度绘制 – 每个像素点在屏幕上绘制了两次。
  • 绿色: 两次过度绘制 – 每个像素点在屏幕上绘制了三次。
  • 粉色: 三次过度绘制 – 每个像素点在屏幕上绘制了四次。
  • 红色: 四次或四次以上过度绘制 – 每个像素点在屏幕上绘制了五次或者五次以上。

最理想的是蓝色,一个像素只绘制一次,合格的页面绘制是白色、蓝色为主,绿色以上区域不能超过整个的三分之一,颜色越浅越好。

避免过度绘制主要有以下几个方案:
1.移除不需要的background。
2.在自定义View的OnDraw方法中,用canvas.clipRect来指定绘制的区域,防止重叠的组件发生过度绘制。

Android绘制优化(二)布局优化的更多相关文章

  1. 【转】Android性能优化之布局优化篇

     转自:http://blog.csdn.net/feiduclear_up/article/details/46670433 Android性能优化之布局优化篇 分类: andorid 开发2015 ...

  2. Android性能优化之布局优化

    最新最准确内容建议直接访问原文:Android性能优化之布局优化 本文为Android性能优化的第二篇——布局优化,主要介绍使用抽象布局标签(include, viewstub, merge).去除不 ...

  3. Android 性能优化 三 布局优化ViewStub标签的使用

    小黑与小白的故事,通过虚拟这两个人物进行一问一答的形式来共同学习ViewStub的使用 小白:Hi,小黑,ViewStub是什么?听说能够用来进行布局优化. 小黑:ViewStub 是一个隐藏的,不占 ...

  4. MySQL性能优化(二):优化数据库的设计

    原文:MySQL性能优化(二):优化数据库的设计 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.n ...

  5. Android开发学习之路--性能优化之布局优化

      Android性能优化方面也有很多文章了,这里就做一个总结,从原理到方法,工具等做一个简单的了解,从而可以慢慢地改变编码风格,从而提高性能. 一.Android系统是如何处理UI组件的更新操作的 ...

  6. Android Studido下的应用性能优化总结--布局优化

    前言:一个应用的成功=产品设计*性能 ,再此我们不讨论一个应用的设计,那交给我们可爱又可恨的产品经理和UI设计师来决定!所以这里分步骤讨论如何提升一个应用的性能,这里先探讨布局优化问题. 布局优化 避 ...

  7. android 优化之布局优化

    布局优化的思路很简单,尽量减少布局文件的层级,看过系统源码的都知道,Android view绘制都是逐层绘制的,所以布局的层级少了,decodeview的时候绘制工作自然就少了. 那么如何进行布局的优 ...

  8. Android性能优化:布局优化 详细解析(含<include>、<ViewStub>、<merge>讲解 )

    1. 影响的性能 布局性能的好坏 主要影响 :Android应用中的页面显示速度 2. 如何影响性能 布局影响Android性能的实质:页面的测量 & 绘制时间 1个页面通过递归 完成测量 & ...

  9. Android 卡顿优化 4 布局优化实际技巧

    今天分享一些layout布局书写中的一些技巧,希望看过之后你也一样可以写出性价比高的布局.我个人的目标是用最少的View写出一样效果的布局.因为我相信View的数量减少伴随着的就是层级的减少.从而达到 ...

  10. Android 卡顿优化 3 布局优化 工具 Hierarchy Viewer

    欲善其事, 先利其器. 分析布局, 就不得不用到Hierarchy Viewer了. 本文工具使用皆以GithubApp的详情界面RepoDetailActivity为例说明. 为了不影响阅读体验, ...

随机推荐

  1. Kubernetes 新时代的宠儿

    本文首发于我的公众号 Linux云计算网络(id: cloud_dev),专注于干货分享,号内有 10T 书籍和视频资源,后台回复「1024」即可领取,欢迎大家关注,二维码文末可以扫. Kuberne ...

  2. [原创]K8飞刀Final

    法律声明: 工具仅供安全研究或授权渗透,非法用途后果自负. 工具: K8飞刀Final作者: K8哥哥博客: https://www.cnblogs.com/k8gege简介: 一款多功能网络安全渗透 ...

  3. State状态模式

    1.简介 在日常开发中,某些对象的状态如果发生改变,对应的行为也将发生改变,那么如何在运行时根据对象的状态动态的改变对象的行为,同时不产生紧耦合关系(即使用if else或者swith所带来的紧耦合关 ...

  4. Spring Aop分析

    前言 上文讲述ioc框架的实现,本文开始讲述aop.在spring中aop也有3种配置方式,注解形式的我们先不讨论.我们先看看xml形式的配置方式. <aop:config> <ao ...

  5. MongoDB从入门到优化

    目录 一.MongoDB 简介 二.MongoDB 的储存引擎 三.mongodb 配置参数 四.MongoDB 单节点搭建 五.MongoDB 连接 六.MongoDB 常用命令 七.MongoDB ...

  6. easyui datagrid列显示图片

    表格头 显示图片 jquery

  7. vsphere 虚拟机的迁移,冷迁移,vmotion(热迁移)

    备注:(理论部分参考王春海老师的课程) 一.概述 1.vsphere数据中心当处于某种目的进行维护时,需要将某台主机上运行或关闭的虚拟机,迁移到其他主机上,这个时候就需要使用迁移 2.可以使用冷迁移或 ...

  8. python下载安装requests库

    一.python下载安装requests库 1.到git下载源码zip源码https://github.com/requests/requests 2.解压到python目录下: 3.“win+R”进 ...

  9. [转]Laravel 数据库实例教程 —— 使用查询构建器实现对数据库的高级查询

    本文转自:https://laravelacademy.org/post/920.html 上一节我们简单介绍了如何使用查询构建器对数据库进行基本的增删改查操作,这一节我们来探讨如何使用查询构建器实现 ...

  10. WPF 列表虚拟化时的滚动方式

    ListBox的滚动方式 分为像素滚动和列表项滚动 通过ListBox的附加属性ScrollViewer.CanContentScroll来设置.因此ListBox的默认模板中,含有ScrollVie ...