如何检测ViewPager中当前Fragment并解决Activity已销毁空指针报错
问题解决方案
报错根因
该报错包含两个关联问题:
- 持有的
activityScenario实例对应的Activity已经被销毁,此时调用onActivity就会抛出空指针异常,通常是页面导航跳转导致旧Activity销毁,没有及时更新activityScenario实例或校验生命周期状态导致 - 使用的
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
相关产品推荐
相关产品推荐

