当前位置: 首页 > news >正文

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

  • 速度极慢,遇到复杂的布局经常超时

  • 某些情况无法选中指定的 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行业感兴趣的新人

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

资料⬅专栏获取

相关文章:

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

速度极慢,遇到复杂的布局经常超时 某些情况无法选中指定的 View 本文将围绕 LayoutInspector 的痛点,分析问题并修复,最终将 LayoutInspector 变成一个稳定、好用的插件。 二、加速 Dump View Hierarchy 2.1 问题描述 开发复杂业务的同学…...

C++ Thead互斥量死锁,mutex如何防止死锁---C++11多线程快速学习

假设有两个线程 T1 和 T2,它们需要对两个互斥量 mtx1 和 mtx2 进行访问,而且需要按照以下顺序获取互斥量的所有权: - T1 先获取 mtx1 的所有权,再获取 mtx2 的所有权。 - T2 先获取 mtx2 的所有权,再获取 mtx1 的所有…...

Ubuntu 之Glade图形化设计器

演示环境说明:本机使用Windows 11 家庭版本搭载 Ubuntu 22.04.4 LTS 子系统,同时并安装Ubuntu桌面虚拟化软件XLaunch。 如果没有搭建好上述问题,请参考:windows11子系统Ubuntu 22.04.4子安装图形化界面 Glade是什么?…...

152. 乘积最大子数组

152. 乘积最大子数组 题目链接&#xff1a;152. 乘积最大子数组 代码如下&#xff1a; class Solution { public:int maxProduct(vector<int>& nums) {int resnums[0];vector<int> f(nums.size()1,0),g(nums.size()1,0);f[0]nums[0],g[0]nums[0];for(int i1…...

proactor模式

Proactor模式是一种异步I/O的设计模式&#xff0c;它允许程序直接发起一个异步I/O操作并立即返回&#xff0c;而不需要等待该操作完成。一旦I/O操作实际完成&#xff0c;系统会通知相应的完成处理程序&#xff08;Completion Handler&#xff09;&#xff0c;该处理程序随后执行…...

Charles抓包工具

一、charles简介 1&#xff0c;charles是什么 Charles中文名叫青花瓷&#xff0c;它是一款基于HTTP协议的代理服务器&#xff0c;通过成为电脑或者浏览器的代理&#xff0c;然后截取请求和请求结果达到分析抓包的目的。 特点:跨平台、半免费 2&#xff0c;charles工作原理 前…...

RabbitMQ如何保证消息可靠

解决办法&#xff1a; 1、做好消息确认机制&#xff08;pulisher、consumer[手动ACK]&#xff09; 2、每一个发送的消息都在数据库做好记录。定期将失败的消息再次发送一遍 消息确认机制&#xff1a; 生产者确认模式&#xff1a;确认消息是否发送到broker&#xff0c;失败…...

学习笔记——路由网络基础——路由的高级特性

七、路由的高级特性 1、路由迭代(路由递归) 路由必须有直连的下一跳才能够指导转发&#xff0c;静态路由或BGP路由的下一跳可能不是直连的邻居&#xff0c;因此需要计算出一个直连的下一跳和对应的出接口&#xff0c;这个过程就叫做路由迭代(路由递归)。 添加一条去往20.1.1.…...

网络编程之XDP、TC和IO_URING以及DPDK

一、网络编程常见的技术 在前面已经分析过了XDP、TC和eBPF。也基本把三者间的关系理清了&#xff0c;但现在又有一个疑惑涌了上来。在前面提到过的IO_URING和DPDK与这些技术有什么关系呢&#xff1f;其实只要认真的看过分析文章可能大家心里都已经基本清楚了。 正如在前面不断…...

晶谷高温烧结导电浆料用低熔点玻璃粉 晶谷耐高温导电漆导电油墨高温玻璃粉

晶谷浆料玻璃粉是一种用于电子浆料的材料&#xff0c;它在电子浆料中起到粘结和降低烧结温度的作用&#xff0c;能够提高浆料与基材之间的结合力。 浆料玻璃粉的性能特点包括&#xff1a; - 软化点&#xff1a;软化点在350至650度之间。 - 热膨胀系数&#xff1a;热膨胀系数…...

【Mysql】DQL操作单表、创建数据库、排序、聚合函数、分组、limit关键字

DQL操作单表 1.1 创建数据库 •创建一个新的数据库 db2 CREATE DATABASE db2 CHARACTER SET utf8;•将db1数据库中的 emp表 复制到当前 db2数据库 ** 1.2 排序** 通过 ORDER BY 子句,可以将查询出的结果进行排序 (排序只是显示效果,不会影响真实数据) 语法结构&#xff1a;…...

Excel 常用技巧(四)

Microsoft Excel 是微软为 Windows、macOS、Android 和 iOS 开发的电子表格软件&#xff0c;可以用来制作电子表格、完成许多复杂的数据运算&#xff0c;进行数据的分析和预测&#xff0c;并且具有强大的制作图表的功能。由于 Excel 具有十分友好的人机界面和强大的计算功能&am…...

【Linux 基础】文件与目录管理

1. 文件和目录的基本概念 文件&#xff1a;是数据的集合&#xff0c;可以是文本、图像、视频等。 目录&#xff08;也称为文件夹&#xff09;&#xff1a;是文件和子目录的集合&#xff0c;用于组织文件。 2. 目录和路径 绝对路径&#xff1a;从根目录&#xff08;/&#x…...

C++系列-String(一)

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” string是用于字符串&#xff0c;可以增删改查 首先&#xff0c;我们来看一下string的底层 接下来&#xff0c;我们来看一下string的常用接口有哪些&#xff1a; #define _CRT_S…...

服务器硬件的基础知识

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

java基于ssm+jsp 汽车在线销售系统

1 前台功能模块 网站首页 网页首页汽车在线销售系统模块如下&#xff1a;首页、汽车信息、新闻资讯、留言反馈、我的收藏管理等功能图1 图1网页首页 网页前台车辆信息效果图如图2所示 图2 车辆信息界面图 2 管理员功能模块 管理员输入个人的账号、密码登录系统&#xff0c…...

【干货】Android中高级开发进阶必备资料(附:PDF+视频+源码笔记)

4、数据传输与序列化 5、Java虚拟机原理 6、高效IO 设计思想解读开源框架 随着互联网企业的不断发展&#xff0c;产品项目中的模块越来越多&#xff0c;用户体验要求也越来越高&#xff0c;想实现小步快跑、快速迭代的目的越来越难&#xff0c;插件化技术应用而生。如果没有…...

AI通用写作模版,可以在此基础上进行修改

指令 角色 作者 &#xff1a;你是一位自媒体爆文写作专家&#xff0c;负责撰写文章&#xff0c;具备对特定主题的深入理解和一定的写作技巧。读者 &#xff1a;25-55岁通用人群&#xff0c;对资讯新闻类感兴趣&#xff0c;需要易于理解且富有启发性的内容。 技能 研究能力&…...

openEuler2203SP3自定义ios

需求&#xff1a; 1、legacy启动 2、/boot分区1G&#xff0c;剩余给/&#xff0c;lvm分区 3、创建root密码和一个普通用户user&#xff0c;密码Hello2024 4、服务器安装&#xff08;选上development、legacy-unix、security-tools&#xff09; 5、关闭firewalld、selinux …...

一年又一年志愿

--第一篇 20220624十年苦读&#xff0c;青春飞扬&#xff0c;其道大光&#xff0c;来日方长。又是一年高考时&#xff0c;高考改变命运&#xff0c;但是后面还有更关键几步&#xff0c;跟大家一起聊聊。之前写我考状元的经历&#xff0c;堂弟考省前十的经历&#xff0c;有不少…...

NL2SQL进阶系列(1):DB-GPT-Hub、SQLcoder、Text2SQL开源应用实践详解

1. MindSQL(库) MindSQL 是一个 Python RAG&#xff08;检索增强生成&#xff09;库&#xff0c;旨在仅使用几行代码来简化用户与其数据库之间的交互。 MindSQL 与 PostgreSQL、MySQL、SQLite 等知名数据库无缝集成&#xff0c;还通过扩展核心类&#xff0c;将其功能扩展到 Sn…...

OpenGL3.3_C++_Windows(15)

理解glad&#xff1a; OpenGL只是一个标准/规范&#xff0c;具体的实现是由驱动开发商针对特定显卡实现的&#xff0c;由于OpenGL驱动版本众多&#xff0c;它大多数函数的位置都无法在编译时确定下来&#xff0c;需要在运行时查询&#xff0c;因此开发者需要在运行时获取函数…...

出海计划 | 赴马来西亚开展水环境项目考察暨2024中马水务合作论坛

报名咨询...

NeRF从入门到放弃5: Neurad代码实现细节

Talk is cheap, show me the code。 CNN Decoder 如patch设置为32x32,patch_scale设置为3&#xff0c;则先在原图上采样96x96大小的像素块&#xff0c;然后每隔三个取一个像素&#xff0c;降采样成32x32的块。 用这32x32个像素render feature&#xff0c;再经过CNN反卷积预测…...

【雷丰阳-谷粒商城 】【分布式高级篇-微服务架构篇】【11】ElasticSearch

持续学习&持续更新中… 守破离 【雷丰阳-谷粒商城 】【分布式高级篇-微服务架构篇】【11】ElasticSearch 简介基本概念ElasticSearch概念-倒排索引安装基本命令Mapping-映射ElasticSearch7-去掉type概念Es-数组&#xff08;数组装着Object&#xff09;的扁平化处理ik 分词…...

Pip换源详解

Pip换源是指将pip&#xff08;Python的包管理工具&#xff09;的默认源更改为其他源。以下是关于Pip换源的详细说明&#xff1a; 一、Pip换源的原因 访问被阻止的源&#xff1a;在某些地区或网络环境下&#xff0c;直接访问官方的Python Package Index (PyPI) 可能受到限制或…...

【Docker】——安装镜像和创建容器,详解镜像和Dockerfile

前言 在此记录一下docker的镜像和容器的相关注意事项 前提条件&#xff1a;已安装Docker、显卡驱动等基础配置 1. 安装镜像 网上有太多的教程&#xff0c;但是都没说如何下载官方的镜像&#xff0c;在这里记录一下&#xff0c;使用docker安装官方的镜像 Docker Hub的官方链…...

利用LinkedHashMap实现一个LRU缓存

一、什么是 LRU LRU是 Least Recently Used 的缩写&#xff0c;即最近最少使用&#xff0c;是一种常用的页面置换算法&#xff0c;选择最近最久未使用的页面予以淘汰。 简单的说就是&#xff0c;对于一组数据&#xff0c;例如&#xff1a;int[] a {1,2,3,4,5,6}&#xff0c;…...

git-pull详解

NAME git-pull - Fetch from and integrate with another repository or a local branch SYNOPSIS git pull [<options>] [<repository> [<refspec>…​]] DESCRIPTION Incorporates changes from a remote repository into the current branch. If the…...

【SQL】count(1)、count(*) 与 count(列名) 的区别

在 SQL 中&#xff0c;COUNT 函数用于计算查询结果集中的行数。COUNT(1)、COUNT(*) 和 COUNT(列名) 都可以用来统计行数&#xff0c;但它们在实现细节和使用场景上有一些区别。以下是详细的解释&#xff1a; 1. COUNT(1) 定义: COUNT(1) 计算查询结果集中的行数。实现: 在执行…...

沧州营销型网站建设/seo一个月工资一般多少

jQuery Ajax 全解析 本文地址: jQuery Ajax 全解析 本文作者&#xff1a;QLeelulu 转载请标明出处&#xff01; jQuery确实是一个挺好的轻量级的JS框架&#xff0c;能帮助我们快速的开发JS应用&#xff0c;并在一定程度上改变了我们写JavaScript代码的习惯。 废话少说&#xff…...

企业品牌网站建设怎么做/百度关键词相关性优化软件

-----------------------往期----------------------------- vuex - 学习日记 vuex - 辅助函数学习 vuex - 常用命令学习及用法整理 vuex - 项目结构目录及一些简单配置 -----------------------正文----------------------------- 首先&#xff0c;目录结构依然如下&#xff1…...

资源网站优化排名网站/福州seo网址优化公司

经常使用的时候找不到&#xff0c;记录一下随时可以看。 快捷键&#xff1a;CTRLB 光标向左移动一个字符CTRLD 删除光标当前所在位置的字符CTRLE 将光标移动到当前行的末尾CTRLF 将光标向右移动一个字符CTRLH 删除光标左侧的一个字符CTRLN 显示历史命令缓冲区中的后一条命令CTR…...

青岛关键词快速排名/优化设计方案

1 <?php2 /**3 * 享元模式4 *5 * 运用享元技术有效的支持大量细粒度的对象6 */7 classCD 8 {9 private$_titlenull;10 private$_artistnull;11 12 publicfunctionsetTitle($title)13 {14 $this->_title $title;15 }16 17 publicfunctiongetTitle()18 {19 return$this-&g…...

站长工具箱/六年级下册数学优化设计答案

组件传参父组件向子组件传值子组件向父组件传值父组件向子组件传值 1. 创建子组件 &#xff0c; 创建一个子组件 ‘ zi.vue’ 2. 在子组件中创建 基本的模本 <template><div><h2> 子组件 </h2><p> {{ message }}</p> </div> <…...

专注高端网站设计/百度地图的精准定位功能

IntelliJ IDEA 默认需要进行maven的设置 需要指定maven的地址&#xff0c;指定settings.xml的地址&#xff1b; 可以默认的在user/.m2/下面放一个settings.xml文件&#xff1b; 学习&#xff1a;http://www.itkeyword.com/doc/8778346909898588127/intellij-idea-cannot-resolv…...