当前位置:网站首页>大厂面试必备技能,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 是否完全包含即可。
最后



边栏推荐
- Windows Oracle open remote connection Windows Server Oracle open remote connection
- 5年经验Android程序员面试27天,2022程序员进阶宝典
- Go语言 | 03 数组、指针、切片用法
- Android面试,android音视频开发
- Redhat7.4 configure Yum software warehouse (rhel7.4)
- 2022全网最全的腾讯后台自动化测试与持续部署实践【万字长文】
- Mysql database indexing tutorial (super detailed)
- 在线协作产品哪家强?微软 Loop 、Notion、FlowUs
- Debezium系列之:修改源码支持unix_timestamp() as DEFAULT value
- Oracle故障处理:Ora-10873:file * needs to be either taken out of backup or media recovered
猜你喜欢
Hiengine: comparable to the local cloud native memory database engine
Low code practice of xtransfer, a cross-border payment platform: how to integrate with other medium-sized platforms is the core
MMO项目学习一:预热
The basic grammatical structure of C language
UWB超宽带定位技术,实时厘米级高精度定位应用,超宽带传输技术
Word finds red text word finds color font word finds highlighted formatted text
2022 the most complete Tencent background automation testing and continuous deployment practice in the whole network [10000 words]
数据库 逻辑处理功能
ELK分布式日志分析系统部署(华为云)
面试官:Redis中集合数据类型的内部实现方式是什么?
随机推荐
Debezium系列之:修改源码支持unix_timestamp() as DEFAULT value
Can Leica capture the high-end market offered by Huawei for Xiaomi 12s?
5. Data access - entityframework integration
ELK分布式日志分析系统部署(华为云)
开源 SPL 消灭数以万计的数据库中间表
关于 Notion-Like 工具的反思和畅想
公司破产后,黑石们来了
How MySQL queries and modifies JSON data
机器学习基础(三)——KNN/朴素贝叶斯/交叉验证/网格搜索
The basic grammatical structure of C language
如何在2022年更明智地应用智能合约?
CF: B. almost Ternary Matrix [symétrie + règles de recherche + Construction + I am Construction Waste]
基于FPGA的超声波测距
Summer Challenge database Xueba notes, quick review of exams / interviews~
HAC集群修改管理员用户密码
Get wechat avatar and nickname with uniapp
Fuzor 2020软件安装包下载及安装教程
Ten years at sea: old and new relay, dark horse rising
Interviewer: what is the difference between redis expiration deletion strategy and memory obsolescence strategy?
如何快速进阶自动化测试?听听这3位BAT大厂测试工程师的切身感想....