如何打造稳定、好用的 Android LayoutInspector?

news2024/11/25 18:52:39
  • 速度极慢,遇到复杂的布局经常超时

  • 某些情况无法选中指定的 View

本文将围绕 LayoutInspector 的痛点,分析问题并修复,最终将 LayoutInspector 变成一个稳定、好用的插件。

二、加速 Dump View Hierarchy


2.1 问题描述

开发复杂业务的同学在使用 LayoutInspector 时都遇到过上图所示的错误:由于 View 树结构复杂超时。网上也有其他相关的解决办法,原理就是修改 timeout 的值,目前默认值是 20s,所以改成 1min,大概率是可以的了。

为了更好的解决这个问题,比如是否能加速?我们看一下整个 LayoutInspector 抓取的流程。梳理流程之前,我们需要找到功能的入口。

2.2 问题分析

2.2.1 Dump 总流程

平常开发者使用 LayoutInspector 的流程一般如下:

  1. 和 Attach debugger 类似,先获取要 LayoutInspector 的进程

  2. 如果进程中不止一个 ViewRootImpl,还需要选择 window

在 IDEA Plugin 框架体系中,大多数插件的功能入口都依赖 Action,上图 LayoutInspector 的功能入口对应的 Action 如何找到呢?最快速、准确的办法就是 Debug,在我们点击功能入口之前,在 AnAction#actionPerformed 加上断点。

从 AndroidRunLayoutInspectorAction 出发,我们找到了真正的任务:

LayoutInspectorCaptureTask。

抓取 View 视图的关键方法如下:

我们可以看到这里先构造了一个 Options,Opentions 中有个参数:ProtocolVersion,目前我们能使用的是 ProtocolVersion.Version1,Goolge 内可以通过 StudioFlags 打开 ProtocolVersion.Version2。

capture view 的流程会比较长,涉及到 adb 通信原理,我们先简单了解一下 adb 通信架构。

  • adb server: 运行在我们的 PC 开发机上,监听 5037 端口

  • adb daemon: 运行在 Android 设备上

  • adb server 通过 USB/tcp 和 adbd 通信

了解了基本的 adb 通信基础之后,我们再来看整个 captureview 的原理:

  1. 通过 ClientWindow 发起 loadWindowData 的请求(在这里可以看到默认超时时间是 20s)

  2. ClinetImpl 收到请求,让 HandleViewDebug 将本次请求封装成 JDWP,然后准备发送

  3. ClientImpl 将数据先发送给本 PC 上的 adb server

  4. adb server 将数据通过 usb/tcp 透传给 Android 设备上的 adbd

  5. Android 设备上的 adbd 根据之前选择的进程信息,将信息再透传给指定的 jdwp 线程

  6. jdwp 通过 native 调用 DDMServer 方法

  7. DdmHandleViewDebug 收到请求开始处理

  8. 处理完请求后,再通过 socket 返回,LayoutInspector 收到结果解析后展示

参考:debugger.cc

  • https://android.googlesource.com/platform/art/+/android-cts-5.0_r9/runtime/debugger.cc#3778

2.2.2 dump v1 原理

在上图的流程中可以看到在最后的调用中,有 dump 和 dumpv2 两个方法,而且 dump 方法已经废弃了。

源码 ViewDebug.java:

看源码我们知道 v1 dump 是获取被 @ExportedProperty 注解作用的 filed 和 method,然后将这些数据写入 ByteArrayOutputStream。比如 View的 padding 属性:

当然也有 method:

上面两图中的 ​
category: padding 和 focus 体现在 LayoutInspector 的属性面板中:

上面看源码的结论:v1 是通过反射遍历所有的 Filed 和 Method。

在我的手机 One Plus7 Android 10 上,View 的 filed 有 487 个,method 有 915 个。写一段简单的代码展示一下仅遍历耗时:

输出:

D/View#dump: 10705ms and 692 views

可以看到我们还没有添加逻辑,仅仅遍历耗时都达到了 10s。

2.2.3 dump v2 原理

看 ViewDebug#dumpv2:

调用到了 View#encode:

相比 v1,v2 就很克制了,只返回有限的数据,需要什么数据就获取什么数据,但不支持自定义的属性,相当于牺牲了一定的灵活性,加快了 dump 的速度。在灵活性、速度两个方面,Google 将 v1 和 v2都保留了,并通过 StudioFlags 提供了开关。

2.3 解决方案

对比完 v1 和 v2 之后,基本可以确定 v2 的速度会快很多了。我们通过自定义 Action,并替换掉原生的 LayoutInspectorCaptureTask,关键是替换下面这个方法:

2.3 效果&收益

v2 相比 v1 速度快了非常多,下面贴一下抖音直播间的 Dump 数据,设备:One Plus 7 Android 10.

LayoutInspector V1: 18803ms

LayoutInspector V2: 328ms

本章节介绍了如何使用 v2 dump 协议来加速,下面介绍第二个痛点:某些情况无法选中指定的 View。

三、精确获取点击的 View

3.1 问题描述

LayoutInspector 还有一个不尽人意的地方——无法选中指定的 View。举个例子:

上图蓝框其实是一个空白的没有内容的 View,这个蓝框盖在了「收礼」这个红圈上。在我们点击这个红圈的时候,却是选中的蓝框。

最后

小编这些年深知大多数初中级Android工程师,想要提升自己,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助

因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

资料⬅专栏获取
点击这个红圈的时候,却是选中的蓝框。

最后

小编这些年深知大多数初中级Android工程师,想要提升自己,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助

因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。

[外链图片转存中…(img-CsurT5bh-1719100969448)]一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

资料⬅专栏获取

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1852483.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaWeb——MySQL:DDL操作库

目录 1.DDL:查询数据库; 1.1 查询数据库 1.2 创建数据库 1.DDL:查询数据库; 具体操作:增 删 查 用 ; 1.1 查询数据库 SQL语句:show databases; 由于我创建过一些数据库,我查询的…

windows无法启动redis-server

Warning: no config file specified, using the default config. In order to specify a config file use D:\Code_enve\Redis\redis-server.exe /path/to/redis.conf Creating Server TCP listening socket *:6379: bind: No such file or directory以上是问题的报错信息&…

做Android开发怎么才能不被淘汰?

多学一项技能,可能就会成为你升职加薪的利器。经常混迹于各复杂业务线的人,才能跳出重复工作、不断踩坑的怪圈。而一个成熟的码农在于技术过关后,更突出其他技能对专业技术的附加值。 毋须讳言的是,35岁以后你的一线coding能力一…

Tableau数据可视化与仪表盘搭建

Tableau的主要目的 数据赋能和数据探索。 数据赋能: 1.分析师可以将数据看板发布到线上给其他部门使用 2.自动更新看板 3.自由下载数据 4.线上修改图表 5.邮件发送数据 6.设置数据预警 数据探索: 1.支持亿级数据的连接和处理 2.自由地对字段进行各种…

【鸿蒙 HarmonyOS】尺寸设置:size/layoutWeight/constraintSize

一、背景 常见尺寸:width(宽度)、height(高度)、padding(内边距)、margin(外边距) 主要整理下size(设置高宽尺寸)、layoutWeight(对…

Go 三色标记法:一种高效的垃圾回收策略

💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

【秋招刷题打卡】Day02-二分系列之-二分查找

Day02-二分系列之-二分查找 前言 给大家推荐一下咱们的 陪伴打卡小屋 知识星球啦&#xff0c;详细介绍 >笔试刷题陪伴小屋-打卡赢价值丰厚奖励 < ⏰小屋将在每日上午发放打卡题目&#xff0c;包括&#xff1a; 一道该算法的模版题 (主要以力扣&#xff0c;牛客&#…

chrome 使用本地替换功能替换接口返回内容

前言 在web开发或测试过程中&#xff0c;我们经常会需要修改接口返回值来模拟数据进行开发或测试。 常用的方式一般通过抓包工具&#xff0c;如charles&#xff0c;或fildder 的功能。 例如我们可以使用charles打断点的方式&#xff0c;或者使用charles的map local 功能进行…

Python18 数据结构与数据类型转换

1.python中的数据结构 在Python中&#xff0c;数据结构是用来存储、组织和管理数据的方式&#xff0c;以便有效地执行各种数据操作。Python提供了几种内置的数据结构&#xff0c;每种都有其特定的用途和操作方法。以下是Python中一些主要的数据结构&#xff1a; 1.列表&#…

【大数据】—量化交易实战案例(基础策略)

声明&#xff1a;股市有风险&#xff0c;投资需谨慎&#xff01;本人没有系统学过金融知识&#xff0c;对股票有敬畏之心没有踏入其大门&#xff0c;所以只能写本文来模拟炒股。 量化交易&#xff0c;也被称为算法交易&#xff0c;是一种使用数学模型和计算机算法来分析市场数…

网络程序通信的流程

网络程序通信的流程&#xff1a; 1.通过ip地址找到网络中的设备 2.通过端口号找到对应进程的端口 3.传输数据时还需要使用传输协议&#xff08;TCP&#xff09;&#xff0c;保证数据的可靠性 4.socket完成进程之间网络数据的传输 ip地址的介绍 IP地址是互联网协议地址&#…

汉语拼音字母表 (声母表和韵母表)

汉语拼音字母表 [声母表和韵母表] 1. 汉语拼音声母表2. 汉语拼音韵母表References 1. 汉语拼音声母表 声母是韵母前的辅音&#xff0c;与韵母一起构成一个完整的音节。 辅音是发声时&#xff0c;气流在口腔中受到各种阻碍所产生的声音&#xff0c;发音的过程即是气流受阻和克…

AtCoder Beginner Contest 359(ABCDEFG题)视频讲解

A - Count Takahashi Problem Statement You are given N N N strings. The i i i-th string S i S_i Si​ ( 1 ≤ i ≤ N ) (1 \leq i \leq N) (1≤i≤N) is either Takahashi or Aoki. How many i i i are there such that S i S_i Si​ is equal to Takahashi? C…

idea2022激活

下载激活脚本 解压后&#xff0c;打开文件夹如下&#xff1a;ja-netfilter.jar 为激活补丁&#xff1a; 复制补丁所在的整个文件夹到硬盘某个位置 将 ja-netfilter补丁所在的整个文件夹移动到电脑上某个位置&#xff0c;我是放到了 D 盘下&#xff1a; &#xff08;路径中不…

Nginx负载均衡之Memcached缓存模块

Nginx 的 ngx_http_memcached_module 模块本身并没有提供缓存功能&#xff0c;它只是一个将用户请求转发到 Memcached 服务器的代理模块。 在以 Memcached 服务器为缓存应用的方案中&#xff0c;Memcached 作为内容缓存的存储服务器&#xff0c;用户通过 URL 为 Memcac…

Android面试题精选——再聊Android-Handler机制

​ static final ThreadLocal sThreadLocal new ThreadLocal(); //创建当前线程的Looper对象 private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() ! null) { throw new RuntimeException(“Only one Looper may be created per thread”); } sThre…

【课程总结】Day10:卷积网络的基本组件

前言 由于接下来的课程内容将围绕计算机视觉展开&#xff0c;其中接触最多的内容是卷积、卷积神经网络等…因此&#xff0c;本篇内容将从卷积入手&#xff0c;梳理理解&#xff1a;卷积的意义、卷积在图像处理中的作用以及卷积神经网络的概念&#xff0c;最后利用pytorch搭建一…

详解互联网基石之HTTPS

一、HTTPS简介 HTTPS&#xff08;HyperText Transfer Protocol Secure&#xff09;是一种用于安全通信的网络传输协议。它是HTTP的加密版本&#xff0c;通过使用TLS&#xff08;Transport Layer Security&#xff09;或其前身SSL&#xff08;Secure Sockets Layer&#xff09;来…

Leetcode3185. 构成整天的下标对数目 II

Every day a Leetcode 题目来源&#xff1a;3185. 构成整天的下标对数目 II 解法1&#xff1a;哈希 本质思路类同经典的“两数之和”。枚举右&#xff0c;用哈希表维护左。 枚举 j&#xff0c;并维护 cnt[x] 表示所有满足 i < j 的下标 i 中&#xff0c;有几个 hours[i]…

服务器硬件的基础知识

引言 服务器是现代数据中心和企业IT基础设施的核心组成部分。了解服务器硬件的基本知识不仅有助于选择和维护服务器&#xff0c;还能提高系统性能和可靠性。本文将详细介绍服务器硬件的各个方面&#xff0c;包括处理器、内存、存储、网络、散热和电源等&#xff0c;帮助读者全…