布局优化:App布局层级分析和渲染速度分析

App布局层级分析和渲染

前沿

关于布局分析的文章,网上太多Hierarchy Viewer相关的文章,但是现在Android Studio 都更新到3.6.X了,这个工具早废弃了,能够真正有用的文章少之又少,所有才有了本篇的文章,使用最新的工具进行App布局层级分析和渲染

目的

基于最新的Android Studio 版本(目前3.6.1),使用最新的工具,进行Android 布局的层级分析和渲染速度分析

一、层级分析

使用Layout Inspector即可实现布局层级的分析,这个还是比较简单的,直接打开tools

1、选择tools->Layout Inspector
在这里插入图片描述
2、在随即显示的 Choose Process 对话框中,选择想要检查的应用进程,然后点击 OK,布局检查器会拍摄快照,将其另存为 .li 文件并打开。
在这里插入图片描述
3、获取的文件如下图所示
在这里插入图片描述

二、渲染速度分析

网上大部分文章都是使用Hierarchy Viewer进行渲染的分析,实际这个以及过时很久了,3.6.2工具都移除了,所以这里使用最新的工具进行渲染速度的分析

官方推荐方法:使用 Window.OnFrameMetricsAvailableListener进行渲染速度的分析

从Android 7.0 (API level 24)开始,Android引入Window.OnFrameMetricsAvailableList接口用于提供每一帧绘制各阶段的耗时,数据源与GPU Profile相同.

查看源码如下:

 public interface OnFrameMetricsAvailableListener {
    void onFrameMetricsAvailable(Window window, FrameMetrics frameMetrics,int dropCountSinceLastInvocation);
}
/**
 * 包含1帧的周期内,渲染系统各个方法的耗时数据.
 */
public final class FrameMetrics {
    ****
    //通过getMetric获取layout/measure耗时所用的id
    public static final int LAYOUT_MEASURE_DURATION = 3;
    public static final int DRAW_DURATION = 4;
    /**
    * 获取当前帧指定id代表的方法/过程的耗时,单位是纳秒:1纳秒(ns)=10的负6次方毫秒(ms)
    */
    public long getMetric(@Metric int id) {
        ****
    }
}

各项指标:

FrameMetrics 指标说明
ANIMATION_DURATION表示执行动画回调的耗时
COMMAND_ISSUE_DURATION表示向 GPU 发出绘制命令的耗时
DRAW_DURATION表示将 View 树转换为 DisplayList 的耗时
FIRST_DRAW_FRAME表示当前帧是否是当前 Window 布局中绘制的第一帧
INPUT_HANDLING_DURATION表示处理输入事件回调的耗时
INTENDED_VSYNC_TIMESTAMP当前帧的预期开始时间, 如果此值与 VSYNC_TIMESTAMP 不同,则表示 UI 线程上发生了阻塞,阻止了 UI 线程及时响应vsync信号
LAYOUT_MEASURE_DURATION表示对 View 树进行 measure 和 layout 所花的时间
SWAP_BUFFERS_DURATION表示将此帧的帧缓冲区发送给显示子系统所花的时间
SYNC_DURATION表示将 DisplayList 与渲染线程同步所花的时间
TOTAL_DURATION表示此帧渲染并发布给显示子系统所花费的总时间, 等于所有其他具有时间价值的指标的值之和
UNKNOWN_DELAY_DURATION表示等待 UI 线程响应并处理帧所经过的时间, 大多数情况下应为0
VSYNC_TIMESTAMP在所有 vsync 监听器和帧绘制中使用的时间值(Choreographer 的帧回调, 动画, View#getDrawingTime等)
时间单位都是纳秒

以上所有指标都存储在一个 long 类型的数组中, 使用 FrameMetrics#getMetric 方法可以从中提取。

在Activity中的使用

新建一个函数,设置addOnFrameTetricsAvailableIListener

val thread = HandlerThread("frame-stat").apply { start() }
val handler = Handler(thread.looper)
window.addOnFrameMetricsAvailableListener(Window.OnFrameMetricsAvailableListener { _, metric,_ ->
    // 会在 handler 对应的 thread 中执行
    val copy = FrameMetrics(metric) /* 注意需要做深拷贝, 再使用 */
    val vsycn = copy.getMetric(FrameMetrics.VSYNC_TIMESTAMP)
    val intended = copy.getMetric(FrameMetrics.INTENDED_VSYNC_TIMESTAMP)
    Log.d("FrameStat", "is first frame: ${copy.getMetric(FrameMetrics.FIRST_DRAW_FRAME) == 1L} ")
    Log.d("FrameStat", "measure layout: ${copy.getMetric(FrameMetrics.LAYOUT_MEASURE_DURATION) / 1000000} ms")
    Log.d("FrameStat", "draw: ${copy.getMetric(FrameMetrics.DRAW_DURATION) / 1000000} ms")
    Log.d("FrameStat", "total: ${copy.getMetric(FrameMetrics.TOTAL_DURATION) / 1000000} ms")
    Log.d("FrameStat", "delay draw: ${copy.getMetric(FrameMetrics.INTENDED_VSYNC_TIMESTAMP) > copy.getMetric(FrameMetrics.VSYNC_TIMESTAMP)} ms")
    Log.d("FrameStat", "=============")
}, handler)

运行结果如下:
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值