绘制优化

No1:

用户能体验到的性能问题主要总结为4类:流畅、稳定、省电、省流量

No2:

Android Studio的优势:

1)稳定速度快:Android Studio使用了单项目管理模式

2)功能强大的UI编辑器:集合了Eclipse+ADT的优点,实时展示界面布局

3)支持多种插件,在线下载

4)直接支持SVN、Git代码管理工具

5)Gradle采用了DSL格式,使得脚本更加灵活简洁

No3:

卡顿的场景有很多,按场景分成4类:UI绘制、应用启动、页面跳转、事件响应

No4:

数据处理导致的卡顿原因是数据处理量太大,分为3种情况:

1)数据处理在UI线程(应避免)

2)数据处理占用CPU高,导致主线程拿不到时间片

3)内存增加导致GC频繁,从而引起卡顿

No5:

Android的显示过程可以简单概括为:Android应用程序把经过测量、布局、绘制后的surface缓存数据,通过SurfaceFlinger把数据渲染到显示屏幕上,通过Android的刷新机制来刷新数据。也就是说应用层负责绘制,系统层负责渲染,通过进程间通信把应用层需要绘制的数据传递到系统层服务,系统层服务通过刷新机制把数据更新到屏幕。

No6:

在Android的每个View绘制中有三个核心步骤,通过Measure和Layout来确定当前需要绘制的View所在的大小和位置,通过绘制(Draw)到surface,在Android系统中整体的绘图源码是在ViewRootImp类的performTraversals()方法,通过这个方法可以看出Measure和Layout都是递归来获取View的大小和位置,并且以深度作为优先级。可以看出,层级越深,元素越多,耗时也就越长。

No7:

影响绘制的根本原因有两方面

1)绘制任务太重,绘制一帧内容耗时太长

2)主线程太忙了,导致VSync信号来时还没有准备好数据导致丢帧

No8:

主线程主要做的工作:UI生命周期控制、系统事件处理、消息处理、界面布局、界面绘制、界面刷新

No9:

从应用层绘制一个页面(View),主要有三个过程:CPU准备数据->GPU从数据缓存列表获取数据->Display设备绘制

No10:

GPU Profile Render-设置-开发者选项-GPU呈现模式分析(条状图)分析渲染时长

No11:

布局优化方法:减少层级

RelativeLayout会对子View做两次测量,如果RelativeLayout中允许子View横向和纵向互相依赖,就需要横向、纵向分别进行一次排序测量。

如果LinearLayout中有weight属性,也需要进行两次测量

1)尽量使用RelativeLayout和LinearLayout

2)在布局层级相同的情况下,使用LinearLayout

3)用LinearLayout有时会使嵌套层级变多,应该使用RelativeLayout,使界面尽量扁平化

No12:

使用Merge的场合主要有以下两处:

1)在自定义View中使用,父元素尽量是FrameLayout或者LinearLayout

2)在Activity中整体布局,根元素需要是FrameLayout

原理是在Android布局的源码中,如果是Merge标签,那么直接将其中的子元素添加到Merge标签Parent中,这样就保证了不会引入额外的层级

No13:

布局优化方法:提高显示速度

<ViewStub 
    android:id="@+id/viewstub_text"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout="@layout/viewstub_text_layout1"/>
ViewStub stub = (ViewStub)view.findViewById(R.id.viewstub_text);
stub.inflate();

注意:ViewStub只能加载一次,指定的布局被加载后,就不能再通过ViewStub来控制它了,所以它不适用于需要按需显示隐藏的情况

ViewStub只能用来加载一个布局文件,而不是某个具体的View

ViewStub中不能嵌套Merge标签

No14:

布局优化方法:布局复用

No15:

影响布局效率主要有以下几点:

1)布局的层级较少,加载速度越快

2)减少同一层级控件的数量,加载速度会变快

3)一个控件的属性较少,解析越快

No16:

Show GPU Overdraw 设置-开发者选项-显示GPU过度绘制

No17:

在开发过程中,尽量使用Application中的Context实例,因为使用Activity中的Context可能会导致内存泄露。也可以使用Activity的getApplicationContext方法。

No18:

冷启动:因为系统会重新创建一个新的进程分配给它,所以会先创建和初始化Application类,再创建和初始化MainActivity类(包括一系列的测量、布局、绘制),最后显示在界面上

热启动:因为会从已有的进程中启动,所以热启动不会再创建和初始化Application,而是直接创建和初始化MainActivity(包括一系列的测量、布局、绘制),即Application只会初始化一次,只包含Activity中的生命周期流程

No19:

UI布局要提高显示的效率,一是减少布局层级,二是避免过度绘制

No20:

启动加载逻辑优化:按需求实现加载逻辑,采取分步加载(以大化小,优先级高的放前)、异步加载(耗时多的异步化)、延期加载策略(非必需的数据延时加载)。

No21:

合理的刷新机制:

1)减少刷新次数

  (1)控制刷新频率:进度条变化最小1%

  (2)避免没有必要的刷新:数据无变化,控件不可见,就没必要刷新

2)避免后台线程影响:比如ListView滚动时,暂停其他UI的操作(比如图片下载)

3)缩小刷新区域

  (1)Android提供了两个局部更新数据的方法:invalidate(Rect dirty)、invalidate(int left,int top,int right,int bottom)

  (2)容器中某个item发生了变化,只需要更新这一个item即可

No22:
帧动画是消耗资源最多,效果最差的一种,能不用就不用

No23:

补间动画实现动画导致View重绘非常频繁。补间动画只能用于View对象,也就是只有继承View或者View的控件,才能用补间动画实现动画效果。

No24:

属性动画可以应用于任何对象,相比于补间动画,属性动画重绘明显少很多,性能也更优秀,所以在实现动画时优先考虑使用属性动画。

No25:

硬件加速的渲染模型中有一个重要的核心类:DisplayList,每个View内部都会维护一个DisplayList。执行绘制的draw()方法会把所有绘制命令记录到一个新的显示列表(DisplayList),这个显示列表包含了输出的View层级的绘制代码。如果只有一个View有变化,只需要重绘这个View,因此可以减少很多的绘图操作次数,明显提高渲染效率。

No26:

硬件加速控制级别

1)Application级别:在Android Manifest中添加

<application android:hardwareAccelerated="true"...>

2)Activity级别:

<activity android:hardwareAccelerated="false/true"/>

3)Window级别

getWindow().setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);

4)View级别

View.setLayerType(View.LAYER_TYPE_SOFTWARE,null);

判断当前View是否已经硬件加速

view.isHardwareAccelerated()或Canvas.isHardwareAccelerated()

No27:

硬件加速可能带来的问题:

1)在软件渲染时,可以使用重用Bitmap的方法来节省内存,但是如果开启了硬件加速,这个方案就不起作用

2)开启硬件加速的View在前台运行时,需要耗费额外的内存,加速的UI切换到后台时,产生的额外内存有可能不释放

3)当UI中存在过渡绘制时,硬件加速会比较容易发生问题。

No28:

卡顿监控方案:Looper中的Printer。

No29:

工具:可以使用Systrace和TraceView分析耗时,使用Hierarchy Viewer来分析页面层级。

原文地址:https://www.cnblogs.com/anni-qianqian/p/7988596.html