Android Gallery 是早期SDK中用于横向滑动展示一组子视图的控件,继承自 AbsSpinner,与 Spinner 共享 AdapterView 的数据绑定机制。对 Gallery 进行测试时,需要同时关注控件内部的选择状态、滑动动画以及 Adapter 数据刷新后的表现。由于 Gallery 已经从官方支持中废弃,很多项目仍保留历史页面,因此测试重点不仅是验证当前功能,还要为后续迁移到 RecyclerView 或 ViewPager2 提供行为基准。

一、Gallery 的工作机制与测试难点
Gallery 通过 AdapterView 的 measure 与 layout 流程将子视图横向排列,并利用 startScroll 等动画将指定位置移动到中心区域。它的选中项由 setSelection 方法控制,滑动结束后会触发 onItemSelected 回调。测试中常见的第一个难点是中心锁定效果:快速滑动时中间项可能跳过回调,如果测试脚本只依赖一次 onItemSelected 来判断结果,容易出现偶发失败。
第二个难点是 Gallery 已经废弃,Espresso 等现代测试框架虽然仍能识别 AdapterView 类型,但官方文档已经不再提供针对 Gallery 的专项支持。部分真机在系统动画缩放或 GPU 渲染差异下,滑动坐标和惯性距离表现不同,导致相同的 swipeLeft 操作在不同设备上选中的项不一致。测试代码需要显式等待 Adapter 数据加载完成,并在执行滑动后通过视图状态或 Activity 内部字段断言结果。
测试准备阶段应在 build.gradle 中引入 Espresso 与 UiAutomator 依赖,并在测试工程中保留一个包含 Gallery 的 Activity。布局文件示例:
<Gallery
android:id="@+id/gallery"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:spacing="8dp"
android:unselectedAlpha="0.6" />
这个布局可以让测试Activity最小化,避免无关控件干扰手势注入。注意 Gallery 的 layout_width 通常设置为 match_parent,子项宽度由 Adapter 的 getView 返回值决定,测试前必须确保子项宽度稳定,否则滑动距离与 item 位置没有固定对应关系。
二、Gallery 核心功能测试用例设计
设计 Gallery 测试用例时,可以先从状态变化角度拆分测试点。初始加载后应选中第 0 项,且中心项透明度或缩放效果符合 unselectedAlpha 配置;调用 setSelection 后应立即触发选中变化;用户左右滑动后,最后稳定在中间位置的项应与 Adapter 数据一致。对于数据动态变化,需要覆盖移除当前选中项、清空数据、重新填充数据三种情况。
- 初始展示:检查 Adapter 数量、第 0 项文本或图片资源是否正确显示。
- 手势切换:执行一次完整滑动后,断言 onItemSelected 被调用,且参数为相邻项。
- 程序切换:调用 setSelection 到指定位置,验证视图位置和选中索引同步。
- 数据变更:调用 notifyDataSetChanged 后,检查选中项索引是否越界或自动回退。
- 空数据:设置空 Adapter,确认没有异常崩溃,且 Gallery 不渲染空白滚动区域。
- 焦点与无障碍:通过键盘方向键或辅助功能事件触发选择,验证焦点项与选中项关系。
这些用例中,手势滑动测试对设备依赖最强。建议先关闭系统动画,或在 Espresso 测试前通过 Developer Options 设置动画缩放为 0,以减少惯性动画对断言时机的影响。对于 onItemSelected 回调,可以通过一个继承自 AdapterView.OnItemSelectedListener 的测试监听器记录回调次数和参数,而不是只依赖 Espresso 的界面断言,这样可以追踪重复触发和跳过触发的问题。
以下是一个测试监听器的简化实现:
public class SelectionRecorder implements AdapterView.OnItemSelectedListener {
public int selectedPosition = -1;
public int callCount = 0;
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
selectedPosition = position;
callCount++;
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
selectedPosition = -1;
}
}
将该监听器注册到 Gallery 后,测试方法可以滑动后直接读取 selectedPosition 和 callCount,既验证结果也暴露异常回调次数。
三、基于 Espresso 的 Gallery 自动化测试
Espresso 对 AdapterView 的测试主要依赖 onData 匹配器。虽然 Gallery 已废弃,但 onData 仍然可以定位其内部项。以下测试演示先匹配任意项,再执行点击选中:
onData(anything())
.inAdapterView(withId(R.id.gallery))
.atPosition(2)
.perform(click());
对于滑动切换,可以直接使用 ViewActions 中的 swipeLeft 和 swipeRight。需要注意的是,swipeLeft 默认从视图 80% 位置滑到 20%,对于 Gallery 这种中心锁定控件,该距离通常足够切换到相邻项,但如果子项宽度较大,应使用 GeneralSwipeAction 自定义滑动起止坐标。
onView(withId(R.id.gallery))
.perform(swipeLeft());
onView(withId(R.id.gallery))
.check(matches(withGallerySelectedPosition(3)));
自定义 Matcher 需要拿到 Gallery 实例并比较 getSelectedItemPosition 返回值。由于 onData 无法直接断言选中索引,可以创建如下匹配器:
public static Matcher<View> withGallerySelectedPosition(final int expected) {
return new BoundedMatcher<View, Gallery>(Gallery.class) {
@Override
public void describeTo(Description description) {
description.appendText("Gallery selected position: " + expected);
}
@Override
protected boolean matchesSafely(Gallery gallery) {
return gallery.getSelectedItemPosition() == expected;
}
};
}
使用这个 Matcher 可以避免依赖界面文本判断,直接验证 Gallery 内部状态。自动滑动如果因为动画未结束而失败,可以插入等待策略,比如在测试代码中轮询 Gallery 的 getSelectedItemPosition,但更推荐使用 Espresso 的 IdlingResource。可以自定义 GalleryIdlingResource,监听 Gallery 的 post 消息或动画状态,当 Gallery 没有正在进行的滚动动画时返回空闲。
除了 Espresso,UiAutomator 更适合跨应用或系统级滑动测试。如果 Gallery 只在一个 Activity 内部使用,Espresso 已经足够;如果需要验证锁屏、跳转其他应用再返回后的状态,可以混合使用 UiAutomator 的 UiDevice 和 UiScrollable。
四、Gallery 废弃后的迁移测试策略
Gallery 在官方 API 中已被标记为 deprecated,新项目不应继续使用。但存量项目维护期间,仍然需要保证 Gallery 功能不回归。因此测试策略应分为两部分:继续用上述方法覆盖旧 Gallery 界面,同时将同样的业务场景迁移到 RecyclerView 或 ViewPager2 后重新执行测试套件,以保证行为一致。
迁移后的 RecyclerView 使用 LinearLayoutManager 横向排列,测试方法从 onData 切换到 RecyclerViewActions。例如点击第 2 项可以写成:
onView(withId(R.id.recycler_gallery))
.perform(RecyclerViewActions.actionOnItemAtPosition(2, click()));
由于 RecyclerView 的选中状态完全由业务代码维护,测试时需要额外断言居中项的高亮、缩放或回调。可以在 Activity 中暴露一个 getSelectedAdapterPosition 方法,让测试代码直接读取,也可以使用自定义 ViewMatcher 检查 item 内的选中标记。相比 Gallery 的内置选中模型,RecyclerView 的测试更灵活,但也更容易遗漏边界条件,例如滚动结束后中间项不是整数位置,或者快速滑动后没有居中。
将 Gallery 测试用例迁移为 RecyclerView 测试时,建议保留原来的测试命名和断言意图,只替换驱动方式。这样可以对比两套控件在相同输入下的输出差异。如果差异仅来自控件动画或焦点策略,则无需修改业务逻辑;如果 RecyclerView 无法复现 Gallery 的居中效果,则说明产品层需要明确新的交互规则。通过这种并行的回归测试,旧 Gallery 页面可以在低风险下继续运行,直到完成替换。
Android Gallery画廊测试Espresso修改时间:2026-08-26 20:05:38