对于一个App的UI而言,在流畅性上的改进目标其实就是降低屏幕绘制的延迟,创建流畅和稳定的帧率以避免卡顿。

在理想情况下,全部的测量、布局和绘制的时间最好在16ms以内,这样才能保证屏幕运行的顺畅性。而如何对屏幕渲染和UI性能进行评估和分析呢,在Android SDK中集成了一些工具用来策略APP的渲染性能问题。

一、视图的层级分析:

对于每一个视图而言,都需要经过三个步骤:测量、布局和渲染。而App如何绘制视图,它需要从顶部节点开始测量,沿着布局树逐个渲染,视图树的层级越多,嵌套测量的次数越多,测量的时间也会越长。而一旦测量完毕就会进行布局,每个视图都会对自己的子视图进行布局,子视图布局完毕后回到父视图,然后再到根视图,布局完成后,每个视图都会被绘制在屏幕上。

显然,App的视图越多,层级越深就需要越长的时间测量、布局和绘制,为了减少这些时间,需要尽可能保持视图层级的扁平化并删除所有没有必要渲染的视图。

虽然在XML布局文件中可以查看布局的节点视图,单很难找到多余的视图,为了找到这些多余的视图,可以利用Android Studio中的Hierarchy Viewer工具来分析Android App中的视图。

Hierarchy Viewer(层次结构查看器)能够便捷地以可视化方式查看各种视图嵌套关系,可用于研究XML视图结构。(需要一个运行Android App的设备)

利用这个工具可以查看我们的View的层次,从而借助它修改我们的布局。

一般的建议:

使用抽象布局标签(include, viewstub, merge)主要是为了优化布局,去除不必要的嵌套和View节点。

  1. 视图重用

多用于ListView和RecylerView等列表形式

  1. 使用include嵌套布局,实现布局的模块化设计,这里需要考虑到下面谈到的merge标签的使用。
  2. <merge>标签

在使用了include后可能导致布局嵌套过多,多余不必要的layout节点,从而导致解析变慢,不必要的节点和嵌套可通过hierarchy viewer或设置->开发者选项->显示布局边界查看。merge标签在UI的结构优化中起着非常重要的作用,它可以删减多余的层级,优化UI。 

merge多用于替换FrameLayout或者当一个布局包含另一个时,merge标签消除视图层次结构中多余的视图组。

merge标签可用于两种典型情况: 

a. 布局顶结点是FrameLayout且不需要设置background或padding等属性,可以用merge代替,因为Activity内容视图的parent
view就是个FrameLayout,所以可以用merge消除只剩一个。 

b. 某布局作为子布局被其他布局include时,使用merge当作该布局的顶节点,这样在被引入时顶结点会自动被忽略,而将其子节点全部合并到主布局中。

  1. <ViewStub>

viewstub标签同include标签一样可以用来引入一个外部布局,不同的是,viewstub引入的布局默认不会扩张,即既不会占用显示也不会占用位置,从而在解析layout时节省cpu和内存。 

viewstub常用来引入那些默认不会显示,只在特殊情况下显示的布局,如进度布局、网络失败显示的刷新布局、信息出错出现的提示布局等。

比如说,假设network_error.xml为只有在网络错误时才需要显示的布局,默认不会被解析。 

当我们要使用的时候,有两种方法可以使用,效果是一样的:

((ViewStub)
findViewById(R.id.layout_error)).setVisibility(View.VISIBLE);

// 或者

View
importPanel = ((ViewStub) findViewById(R.id.layout_error)).inflate();

二、资源缩减

第一点提到的是将App的视图结构变扁平,减少视图的数量后,其实我们还可以尝试减少每个视图里使用的资源数量。(如加载时引用一个资源,在运行时进行着色)

三.屏幕的过度绘制

屏幕的过度绘制这个概念有点类似于PhotoShop中的图层的概念,上面的图层会覆盖住下面的图层,而使得下面的图层不可见。当Android系统绘制屏幕时,首先绘制父视图而后是子视图,子视图位于其父视图上。

重绘屏幕的行为被称为过度绘制,多次的屏幕绘制会增加延迟,并且可以导致布局卡顿。

既然过度绘制的影响那么大,我们应该怎么检测呢?

Android提供了一些很好的工具来检测过度绘制,而一般采用的方式是在Debug GPU Overdraw菜单中选择“Show Overdraw area”,(在本人手机中为开发者选项中的调试GPU过度绘制),选择之后会在App的不同区域覆盖不同的颜色来表示过度绘制的次数。比较屏幕上的这些不同颜色,可以快速定位问题。

白色:没有过度绘制

蓝色:1次过度绘制(屏幕绘制了2次)

绿色:2次过度绘制

浅红色:3次过度绘制

深红色:4次或更多次过度绘制

而另外一种查看方法是借助于前面提到的Hierarchy Viewer工具,将view hierarchy保存为Photoshop文档,打开这些视图后可以看到不同层次的过度绘制情况。

四、分析卡顿(策略GPU的渲染能力)

在优化视图的层次结构和过度绘制后,App还存在丢帧或者不流畅的情况,为了获得获得更加全面的卡顿检测信息,Android系统中有一个Profile GPU Rendering的开发者选项,它能够检测出每一帧在屏幕上用了多久,策略数据可以保存到日志文件中,或者在设备上实时显示。一般而言,在屏幕上直接展示GPU的渲染数据能够更加直观地看到。

在本人的手机中,在开发者选项中找到【GPU呈现模式分析】,选择【在屏幕上显示为条形图】,然后打开一个手机QQ,就发现如下图所示情况

需要关注的是底部的那一条水平绿线,它表示设备渲染一帧要16ms,每一帧就是一个水平条,如果有很多帧超过了这条绿线就说明设备出现了卡顿情况。

五、让它看起来更快

前面讲到了如果通过测试发现问题优化布局使得UI绘制更加流畅,其实还有一个方法使得UI绘制更快:让它看起来更快。

  1. 进度条
  2. 动画
  3. 即时更新:指用户更新了一个页面后,页面上的数据就会立刻发生变化,即使数据还没有达到服务器(这里需要确定这些数据最终一定可以更新到服务器)(离线上传,离线发送网络请求)

或者是另外一种思路,在用户添加有关图片帖子的文字时提前上传图片到服务器。

Android的UI调优的更多相关文章

  1. Android界面性能调优手册

    界面是 Android 应用中直接影响用户体验最关键的部分.如果代码实现得不好,界面容易发生卡顿且导致应用占用大量内存. 我司这类做 ROM 的公司更不一样,预装的应用一定要非常流畅,这样给客户或用户 ...

  2. android性能测试与调优:使用 DDMS 查看内存分配情况

    1. 启用自己的APK后 2. 点击左边更新heap 3. 点击右边的heap中的垃圾回收cause GC,等待数秒出现回收内存与数据情况(由于内存回收了APK运行出现异常crash) 4. 点击一个 ...

  3. Android系统性能调优工具介绍

    http://blog.csdn.net/innost/article/details/9008691 经作者授权,发表Tieto某青年牛的一篇<程序员>大作. Android系统性能调优 ...

  4. 【Java/Android性能优3】Android性能调优工具TraceView使用介绍

    本文转自:http://blog.csdn.net/innost/article/details/9008691 在软件开发过程中,想必很多读者都遇到过系统性能问题.而解决系统性能问题的几个主要步骤是 ...

  5. 【Java/Android性能优2】Android性能调优工具TraceView介绍

    本文参考:http://www.trinea.cn/android/android-traceview/ Android自带的TraceView堪比java的性能调优工具visualvm线程视图,可以 ...

  6. 转: 腾讯Bugly干货分享:Android应用性能评测调优

    转:http://www.kuqin.com/shuoit/20150618/346693.html?utm_source=www.race604.com 前言 在智能手机App竞争越来越激烈的今天, ...

  7. Android性能调优篇之探索垃圾回收机制

    开篇废话 如果我们想要进行内存优化的工作,还是需要了解一下,但这一块的知识属于纯理论的,有可能看起来会有点枯燥,我尽量把这一篇的内容按照一定的逻辑来走一遍.首先,我们为什么要学习垃圾回收的机制,我大概 ...

  8. 【Java/Android性能优化1】Android性能调优

    本文参考:http://www.trinea.cn/android/android-performance-demo/ 本文主要分享自己在appstore项目中的性能调优点,包括同步改异步.缓存.La ...

  9. Android性能调优

    本文主要分享自己在appstore项目中的性能调优点,包括同步改异步.缓存.Layout优化.数据库优化.算法优化.延迟执行等.一.性能瓶颈点整个页面主要由6个Page的ViewPager,每个Pag ...

随机推荐

  1. Omi树组件omi-tree编写指南

    Omi框架能够以少量的代码声明式地编写可拖拽移动节点的树形组件. 通常树组件能够考验UI框架的健壮性,因为需要使用到UI框架的如下特性: 组件嵌套 组件传值 组件批量传值 组件依赖自身递归嵌套(nes ...

  2. UVA 10905 Children's Game (贪心)

    Children's Game Problem Description There are lots of number games for children. These games are pre ...

  3. AngularJS2基本构造

    2.NG2入门 2.1 基本构造 angularjs主要有8个构造快: 模块(module) 组件(component) 模板(template) 元数据(metadata) 数据绑定(data bi ...

  4. Quartz (一)

    1 核心接口 1.1 Scheduler---核心调度器 1.2 Job---任务 1.3 JobDetail---任务描述 1.4 Trigger---触发器 2 触发器 Tigger(CornTr ...

  5. 使用命令行的方式操作hdfs

    必须要用打全路径,没有相对路径的概念,或者cd的概念 打印报告: 所有的命令显示出来: 以下的操作分别是创建创建文件夹,删除文件夹,显示文件夹,可见删除文件夹只能够使用-rmr . 从本地拷贝文件到h ...

  6. 白话C#语法新特性之元组

    1.元组(Tuples) 元组(Tuple)在4.0 的时候就有了,但元组也有些缺点,如: 1)Tuple 会影响代码的可读性,因为它的属性名都是:Item1,Item2.. . 2)Tuple 还不 ...

  7. 学习笔记:javascript内置对象:字符串对象

    1.字符串的创建   var str = "Hello Microsoft!";   2.字符串属性   constructor  返回创建字符串属性的函数   length    ...

  8. [刷题]算法竞赛入门经典 3-10/UVa1587 3-11/UVa1588

    书上具体所有题目:http://pan.baidu.com/s/1hssH0KO 题目:算法竞赛入门经典 3-10/UVa1587:Box 代码: //UVa1587 - Box #include&l ...

  9. python selenium 元素定位(三)

    上两篇的博文中介绍了python selenium的环境搭建和编写的第一个自动化测试脚本,从第二篇的例子中看出来再做UI级别的自动化测试的时候,有一个至关重要的因素,那就是元素的定位,只有从页面上找到 ...

  10. 开涛spring3(1) - Spring概述

    1.1.1  Spring是什么 Spring是一个开源的轻量级Java SE(Java 标准版本)/Java EE(Java 企业版本)开发应用框架,其目的是用于简化企业级应用程序开发.应用程序是由 ...