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

如何检测ViewPager中当前Fragment并解决Activity已销毁空指针报错

问题解决方案

报错根因

该报错包含两个关联问题:

  1. 持有的activityScenario实例对应的Activity已经被销毁,此时调用onActivity就会抛出空指针异常,通常是页面导航跳转导致旧Activity销毁,没有及时更新activityScenario实例或校验生命周期状态导致
  2. 使用的getLastFragment()方法没有正确从ViewPager中获取对应位置的Fragment,逻辑本身存在缺陷

修复步骤

1. 修复ActivityScenario生命周期异常

  • 不要持有全局的activityScenario实例,每次调用onActivity前先校验Activity的生命周期状态,确保Activity处于活跃状态再执行后续逻辑:
// 调用onActivity前增加状态校验
if (activityScenario?.state?.isAtLeast(Lifecycle.State.CREATED) == true) {
    activityScenario.onActivity { 
        // 校验Fragment逻辑
    }
}
  • 如果测试流程会跳转多个Activity,建议每次切换Activity后重新获取对应新Activity的activityScenario实例,不要复用旧实例。

2. 正确获取ViewPager中的Fragment

根据使用的ViewPager版本选择对应方案:

方案A:针对androidx.viewpager.widget.ViewPager

系统原生的FragmentPagerAdapter/FragmentStatePagerAdapter会给每个Fragment设置固定格式的Tag,规则为"android:switcher:${ViewPager的资源ID}:${Fragment对应的位置}",可以通过Tag直接获取:

fun getViewPagerFragment(fm: FragmentManager, viewPagerId: Int, position: Int): Fragment? {
    return fm.findFragmentByTag("android:switcher:$viewPagerId:$position")
}

// 测试时调用示例
activityScenario.onActivity {
    // 假设ViewPager id是R.id.dashboard_view_pager,Map Tab在第0位
    val mapFragment = getViewPagerFragment(it.supportFragmentManager, R.id.dashboard_view_pager, 0)
    assertTrue(mapFragment is DetectionMapFragment)
}

方案B:针对androidx.viewpager2.widget.ViewPager2

ViewPager2基于RecyclerView实现,可以在PagerAdapter中存储Fragment的弱引用(避免内存泄漏),对外暴露获取对应位置Fragment的方法:

// 首先修改PagerAdapter代码
class DashboardPagerAdapter(activity: FragmentActivity) : FragmentStateAdapter(activity) {
    // 用弱引用存储Fragment,避免内存泄漏
    private val fragmentRefs = SparseArray<WeakReference<Fragment>>()

    override fun createFragment(position: Int): Fragment {
        val fragment = when(position) {
            0 -> DetectionMapFragment()
            1 -> DashboardFragment()
            else -> error("无效的Tab位置")
        }
        fragmentRefs.put(position, WeakReference(fragment))
        return fragment
    }

    fun getFragmentAtPosition(position: Int): Fragment? {
        return fragmentRefs.get(position)?.get()
    }
}

// 测试时调用示例
activityScenario.onActivity {
    val viewPager = it.findViewById<ViewPager2>(R.id.dashboard_view_pager)
    val adapter = viewPager.adapter as DashboardPagerAdapter
    // 获取当前选中位置的Fragment
    val currentFragment = adapter.getFragmentAtPosition(viewPager.currentItem)
    assertTrue(currentFragment is DashboardFragment)
}

3. 更推荐的UI测试校验方案

UI自动化测试建议优先用黑盒校验方式,不需要获取Fragment实例,直接校验对应Fragment专属的UI元素是否显示即可,完全规避Activity生命周期问题:
比如DetectionMapFragment中有唯一的地图控件R.id.map_view,切换到Map Tab后直接校验该控件是否展示即可:

step("校验Map Tab切换成功") {
    dashboardScreen.mapView.check { isDisplayed() }
}

内容的提问来源于stack exchange,提问作者Saygın Dikbayır

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 04:06:01