背景
小组做了一个APP遍历的功能,之前我一直没有看。这两天看源代码整理思路。本来想和其他2个Android遍历产品放在一起做一个对比。但是,后来发现文章太长了,所以独立出来。
遍历需要解决的问题
操作元素
操作元素包括定位元素和操作元素两大块。最主要的是定位元素
- 定位元素
定位元素的方法有很多: 包括根据resource-id,name,以及xpath。精确度最高的是resource-id,但不是每一个元素都会有这个属性,所以这个思路废弃。我们小组采用的是xpath定位。在操作元素之前,给每个元素唯一的xpath,具体值怎么计算的,在遍历流程那里细讲。 - 操作元素成功或者失败
我们有三个列表来保存操作成功的元素,操作失败的元素,未操作的元素
页面处理
- 如何定义一个新的页面
当操作一个元素之后,怎么判断页面是否发生变化?这是遍历算法需要解决的另外一个问题。 我们给每一个页面标识了一个md5值。这个md5值的算法是这样的:- 遍历新页面的每一个node,给每一个node 设置xpath。xpath是这样计算的:
子节点的 xpath = 父节点的xpath + 子节点name + (与子节点name一样的个数)
来保证每个节点xpath的唯一性。 - 然后将步骤1获得所有节点的xpath值进行拼接,计算md5值作为当前页面的md5值。
- 遍历新页面的每一个node,给每一个node 设置xpath。xpath是这样计算的:
回退流程
(还有一个问题,难道页面发生变化之后,node还保留?)
那么,最重要的来了,当操作一个元素之后,接下来的流程是什么呢?
- 如果进入新的页面
我们有一个表notTravel,其中存储的是每一个页面的没有遍历过的节点。当进入一个新的页面时,会将这个页面所有有效节点加入notTravel- 新页面曾经遍历过,但是没有遍历完成。
从notTravel 中将新页面所有节点,提到最前面 - 新页面曾经遍历过,而且所有节点都遍历结束
会试着移动页面,找到新的遍历页面(?什么操作)。如果移动页失败的话,回退到上一个页面。再执行一遍页面操作的流程。 - 新页面没有遍历过
将新页面的所有节点加入notTravel ,并且提前到notTravel表的最前面。
- 新页面曾经遍历过,但是没有遍历完成。
- 如果停留在老的页面
1.如果老的页面已经结束
会试着移动页面,找到新的遍历页面(?什么操作)。如果移动页失败的话,回退到上一个页面。再执行一遍页面操作的流程。
循环回退流程,直到所有的notTravel 中不存在节点了。
- checksource是干嘛用的?
1.如果新页面中有元素可以进入到老的页面
首先回退到老的页面,然后老的页面走一遍页面处理流程;如果停留在新的页面,继续遍历新的页面;如果进入第三方页面,遍历第三方页面。
2.如果没有
继续遍历新的页面
遍历流程
基本流程图如下所示啦
image.png
网友评论