You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kakao/Kaspresso中多ViewType RecyclerView点击问题求助

基于Kaspresso/Kakao实现多ViewType RecyclerView的首个普通项点击

我在使用Kakao进行UI测试时,遇到了多ViewType RecyclerView的操作问题:该RecyclerView作为自动补全组件,包含两种ViewType:

  • 普通结果项(布局ID为 auto_completer_item_root)
  • 周边搜索特殊项(布局ID为 gps_search_item_root)

我的需求是点击RecyclerView中第一个属于普通类型的项,但当前列表的首个项是上述特殊类型。


对应的视图布局代码

普通结果项布局

<androidx.constraintlayout.widget.ConstraintLayout 
    ...
    android:id="@+id/auto_completer_item_root" ...>

    <TextView
        android:id="@+id/destination_title"
        ...
    />
    ...
</androidx.constraintlayout.widget.ConstraintLayout>

周边搜索特殊项布局

<androidx.constraintlayout.widget.ConstraintLayout 
    ...
    android:id="@+id/gps_search_item_root" ...>

    <TextView
        android:id="@+id/gps_title"
        ...
    />
    ...
</androidx.constraintlayout.widget.ConstraintLayout>

已实现的Screen对象代码

class AutoCompleterScreen : KScreen<AutoCompleterScreen>() {

    override val layoutId: Int? = null
    override val viewClass: Class<*>? = null

    val resultList = KRecyclerView(
        builder = { withId(R.id.destinationList) },
        itemTypeBuilder = {
            itemType(::GpsSearch)
            itemType(::AutoCompleterResult)
        }
    )

    internal class AutoCompleterResult(parent: Matcher<View>) : KRecyclerItem<AutoCompleterResult>(parent) {
        val title: KTextView = KTextView(parent) { withId(R.id.destination_title) }
    }

    internal class GpsSearch(parent: Matcher<View>) : KRecyclerItem<GpsSearch>(parent) {
        val title: KTextView = KTextView(parent) { withId(R.id.gps_title) }
    }
}

尝试过的无效写法

  1. 原本预期生效,但实际无响应:
onScreen<AutoCompleterScreen> {
    resultList {
        firstChild<AutoCompleterScreen.AutoCompleterResult> {
            title {
                click()
            }
        }
    }
}
  1. 偶然成功一次但无法复现(推测和应用未全新安装有关):
onScreen<AutoCompleterScreen> {
    resultList {
        childWith<AutoCompleterScreen.AutoCompleterResult> {
            withId(R.id.auto_completer_item_root)
            isFirst()
        } perform {
            click()
        }
    }
}

可正常工作的Espresso实现

我已经写出了可以正常运行的Espresso代码,但希望基于Kaspresso框架实现相同逻辑:

onView(withId(R.id.destinationList))
  .perform(actionOnFirstItemWithId(R.id.auto_completer_item_root, click()))

对应的辅助方法:

fun actionOnFirstItemWithId(@IdRes viewId: Int, action: ViewAction): ViewAction {

    return object : ViewAction {
        override fun getConstraints(): Matcher<View> {
            return Matchers.allOf(ViewMatchers.isAssignableFrom(RecyclerView::class.java), ViewMatchers.isDisplayed())
        }

        override fun getDescription(): String {
            return "Perform action on the first item that has a view with the given ID."
        }

        override fun perform(uiController: UiController, view: View) {
            val recyclerView = view as RecyclerView
            for (i in 0 until recyclerView.adapter!!.itemCount) {
                uiController.loopMainThreadForAtLeast(500)
                val viewHolder = recyclerView.findViewHolderForAdapterPosition(i)
                if (viewHolder?.itemView?.findViewById<View>(viewId) != null) {
                    if (i != 0) {
                        recyclerView.scrollToPosition(i)
                        uiController.loopMainThreadForAtLeast(500)
                    }
                    val targetView = viewHolder.itemView.findViewById<View>(viewId)
                    action.perform(uiController, targetView)
                    return
                }
            }
        }
    }
}

我推测Kakao/Kaspresso可能在主线程循环处理上存在问题,但框架自带的防抖实现应该不需要手动处理主线程循环。求基于Kaspresso/Kakao实现需求的方案。


内容的提问来源于stack exchange,提问作者ceedee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 00:54:54