当前位置:网站首页>大厂面试必备技能,2022Android不死我不倒
大厂面试必备技能,2022Android不死我不倒
2022-07-05 19:04:00 【InfoQ】
先上一份面试资料目录
业内情况
无痕埋点
可视化埋点
阶段一:无痕埋点
无痕埋点技术实现
页面ID规则
- Activity,ID 规则为
ActivityClassName|额外参数
- Fragment,ID 规则为
ActivityClassName[FragmentClassName]|额外参数
页面PV、UV
onResume()
onResume()
setUserVisibleHint(boolean isVisibleToUser)
onHiddenChanged(boolean hidden)
- Activity

- Fragment

控件ID规则

FrameLayout[0]/LinearLayout[1]/Button[0]



控件ID的优化

FrameLayout[0]/LinearLayout[2]/Button[0]
- 优化1:将兄弟节点中的位置,变成相同类型控件的位置。优化后的控件路径为:
FrameLayout[0]/LinearLayout[1]/Button[0]
,即使在插入 FrameLayout 后,其路径仍旧不变,相较之前会更加稳定一些。但如果插入的是 LinearLayout,或者整个页面的 UI 进行了重构,控件路径依旧会发生改变。
- 优化2:因为不同的系统版本或手机厂商,会对页面的根 View 做一定的处理,所以我们需要屏蔽掉这种情况,对于我们而言,我们只关心我们自定义的那部分布局,即通过 setContentView 传入的布局。我们可以通过判断控件 ID 是否等于
android.R.id.content
来获取我们自定义的布局的根 View,并将其作为我们控件路径的起点。
- 优化3:在 Android 中,除了
R.id
和控件路径之外,还有一个比较常用的可以作为控件 ID 的特征信息,那就是开发者写在布局文件中,关联控件的 Resource ID。Resource ID 是开发者自己定义的关联 View 的标识,在一个页面当中,理论上是唯一的(为什么说是理论上,因为还是存在有多个相同 Resource ID 的情况,比如动态的 add 多个 layout,且包含了相同的 Resource ID,但这种情况非常少),并且在页面的重构过程中,Resource ID 也一般不会修改,因此用 Resource ID 来作为控件 ID 是非常合适的。但并不是所有的控件都有 Resource ID,我们可以先尝试去获取这个 ID,假如 Resource ID 存在,则使用 Resource ID 来作为控件 ID,假如 Resource ID 不存在,则降级使用控件路径作为控件 ID。核心代码如下:

控件的点击、长按指标
onClick(View v)
onLongClick(View v)
- 点击

- 长按

代码插桩
Javassist

gradle 插件


- 先根据类名得到
CtClass
对象
- 再根据我们想要寻找的切入点,页面就找
onResume()
方法,控件就找onClick(View view)
方法
- 然后根据方法名和参数类型,得到
CtMethod
对象
- 调用
CtMethod
对象的编辑方法体的 API,在原始方法体之前插入就调用insertBefore
,之后就调用insertAfter
,传入需要插入的代码块
- 调用
CtClass
的writeFile()
方法,保存这次编辑
阶段二:可视化管理后台


上报控件信息
- 可被点击或长按
- 在当前界面可见


- 判断 View 本身可见性属性
- View 本身可见性属性比较容易判断,我们只需要判断
View.isShown()
并且View.getVisibility() == View.VISIBLE
即可。
- 判断 View 所处的位置是否在当前屏幕内
- 一个 Activity 加载了多 Fragment 的情况下,可能会出现控件本身可见性属性达标,但实际并不在屏幕内的情况。这种情况我们根据
View.getLocationOnScreen(int[] outLocation)
,然后通过判断outLocation[0]
,是否大于等于 0 且小于等于屏幕宽度,就能判断控件是否在当前屏幕内。
- 判断控件是否被其他控件完全遮挡
- 遍历所有与该控件有关联的控件(同层控件、父控件、父控件的同层控件等),通过
View.getGlobalVisibleRect(Rect viewRect)
来得到控件所对应的 Rect 信息,然后通过Rect.contains(Rect r)
来判断两个控件对应的 Rect 是否完全包含即可。
最后



边栏推荐
- 彻底理解为什么网络 I/O 会被阻塞?
- Windows Oracle open remote connection Windows Server Oracle open remote connection
- PG基础篇--逻辑结构管理(用户及权限管理)
- 从外卖点单浅谈伪需求
- Mariadb root用户及普通用户的密码 重置
- R语言使用lubridate包处理日期和时间数据实战
- Postman核心功能解析-参数化和测试报告
- Tianyi cloud understands enterprise level data security in this way
- 【历史上的今天】7 月 5 日:Google 之母出生;同一天诞生的两位图灵奖先驱
- MMO项目学习一:预热
猜你喜欢
Tutoriel de téléchargement et d'installation du progiciel fuzor 2020
Oracle故障处理:Ora-10873:file * needs to be either taken out of backup or media recovered
【AI 框架基础技术】自动求导机制 (Autograd)
【历史上的今天】7 月 5 日:Google 之母出生;同一天诞生的两位图灵奖先驱
如何实现游戏中的在线计时器和离线计时器
华为让出的高端市场,小米12S靠徕卡能抢到吗?
Advanced application of C # language
在线协作产品哪家强?微软 Loop 、Notion、FlowUs
How to quickly advance automated testing? Listen to the personal feelings of the three bat test engineers
面试官:Redis 过期删除策略和内存淘汰策略有什么区别?
随机推荐
The road of enterprise digital transformation starts from here
如何快速进阶自动化测试?听听这3位BAT大厂测试工程师的切身感想....
Benefits of automated testing
MMO項目學習一:預熱
Technology sharing | common interface protocol analysis
为什么 BI 软件都搞不定关联分析?带你分析分析
Mysql如何对json数据进行查询及修改
golang通过指针for...range实现切片中元素的值的更改
出海十年:新旧接力,黑马崛起
Shang Silicon Valley Shang preferred project tutorial release
The problem of returning the longtext field in MySQL and its solution
Tianyi cloud understands enterprise level data security in this way
决策树与随机森林
shell编程基础(第9篇:循环)
C# 语言的基本语法结构
Decision tree and random forest
公司破产后,黑石们来了
5 years of experience, 27 days of Android programmer interview, 2022 programmer advanced classic
Word finds red text word finds color font word finds highlighted formatted text
Get wechat avatar and nickname with uniapp