首页 > 代码库 > [UiAutomator] UiSelector中instance与index的用法

[UiAutomator] UiSelector中instance与index的用法

在使用UiAutomator写测试用例时,最常用到的就是控件查找操作。

在UiSelector中,有两个定位控件的方法,一个是instance,一个是index。那么这两个方法有什么区别呢?

首先,我们看一下官方api说明:

instance(int instance):
Set the search criteria to match the widget by its instance number. The instance value must be 0 or greater, where the first instance is 0. For example, to simulate a user click on the third image that is enabled in a UI screen, you could specify a a search criteria where the instance is 2, the className(String) matches the image widget class, and enabled(boolean) is true. The code would look like this: new UiSelector().className("android.widget.ImageView") .enabled(true).instance(2);

index(int index):
Set the search criteria to match the widget by its node index in the layout hierarchy. The index value must be 0 or greater. Using the index can be unreliable and should only be used as a last resort for matching. Instead, consider using the instance(int) method.

也就是说instance方法会将界面上所有相同类型的控件按顺序取出来,放到一个集合里(暂且这么理解吧,不知道放哪里了,囧),然后按照控件在集合的角标把想要的控件取出来;而index则是通过该控件所在层级的节点角标将对应的控件取出来。

那么这两个方法到底是怎么使用的呢?看下面的例子:

首先我们通过xml定义一个布局:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    tools:context=".MainActivity" >    <TextView        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:gravity="center_horizontal"        android:text="textview1"        android:textSize="22sp" />    <Button        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="button1" />    <TextView        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:gravity="center_horizontal"        android:text="textview2"        android:textSize="22sp" />    <Button        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="button2" />    <TextView        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:gravity="center_horizontal"        android:text="textview3"        android:textSize="22sp" /></LinearLayout>

使用UiAutomatorViewer截出来的图是这样的:

技术分享

按照说明,使用index方法获取TextView控件是这样的:

UiObject obj = new UiObject(new UiSelector().className("android.widget.TextView").index(0)); // textview1UiObject obj = new UiObject(new UiSelector().className("android.widget.TextView").index(2));  // textview2UiObject obj = new UiObject(new UiSelector().className("android.widget.TextView").index(4));  // textview3

哎,等等,尼玛!为啥我第一个方法取到的UiObject是“TestUI”,原来在我们的TitleBar上也有一个TextView控件,而它的节点角标也是0(见下图)。这是不是太坑爹了?先不要埋怨,人家api文档都说的很清楚了,这是一个不靠谱(unreliable)的方法,其他方法都不好使了才建议去尝试此方法。

技术分享

下面把使用instance方法获取TextView控件的方法写出来:

UiObject obj = new UiObject(new UiSelector().className("android.widget.TextView").instance(0)); // TestUI
UiObject obj = new UiObject(new UiSelector().className("android.widget.TextView").instance(1)); // textview1UiObject obj = new UiObject(new UiSelector().className("android.widget.TextView").instance(2));  // textview2UiObject obj = new UiObject(new UiSelector().className("android.widget.TextView").instance(3));  // textview3

怎么样,使用instance方法就靠谱多了吧。

本次分享到此结束,欢迎大家与我一起交流。

============================2014-12-25 分割线===================

今天上网看博客,发现index方法还有一种用法,就是在UiObject.getChild()方法里使用。还是以上面的UI为例。

如果我们想要获取textview1对应的TextView控件,首先找到它的父控件LinearLayout,而LinearLayout又是FrameLayout的子控件(如下图)。

技术分享

所以,获取textview1的代码大概是这样:

UiObject viewObj = new UiObject(new UiSelector().className("android.view.View")); // 获取View控件UiObject flObj = viewObj.getChild(new UiSelector().index(1)); // 获取FrameLayout控件UiObject llObj = flObj.getChild(new UiSelector().index(0)); // 获取LinearLayout控件UiObject tv1Obj = llObj.getChild(new UiSelector().index(0)); // 获取textview1对应的TextView控件

怎么样?还是instance好用吧!

 

[UiAutomator] UiSelector中instance与index的用法