如何在Activity销毁前仅对ViewPager内当前前台Fragment执行指定操作
解决方法
核心逻辑为仅对用户真实可见的Tab对应的Fragment执行标记已读操作,管控触发时机即可,两种可落地实现方案如下:
方案1:宿主Activity统一管控(更推荐,逻辑集中不易出错)
将触发逻辑统一放到Activity层面处理,无需改动Fragment代码:
- 在ViewModel中新增当前选中Tab的存储字段:
// 共享ViewModel中添加 val currentSelectedTab = MutableLiveData<Int>(0) // 默认选中第一个Tab
- 在Activity初始化Tab时添加选中监听,切换Tab时直接触发被切走Tab的标记逻辑:
// TabLayout和ViewPager2绑定逻辑 TabLayoutMediator(inbox_tab, viewpager) { tab, position -> // 原有Tab配置逻辑,比如设置Tab标题 }.attach() // 添加Tab选中监听 inbox_tab.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener { override fun onTabSelected(tab: TabLayout.Tab) { // 更新当前选中的Tab位置 inboxViewModel.currentSelectedTab.value = tab.position } override fun onTabUnselected(tab: TabLayout.Tab) { // Tab被切走时直接触发该Tab的已读标记逻辑 inboxViewModel.markNotificationsAsRead(tab.position) } override fun onTabReselected(tab: TabLayout.Tab) = Unit })
- 重写Activity的
onPause方法,处理用户离开当前页面的场景:
override fun onPause() { super.onPause() // 仅对当前选中的Tab执行已读标记 inboxViewModel.currentSelectedTab.value?.let { inboxViewModel.markNotificationsAsRead(it) } }
方案2:Fragment内部自行管控
如果希望逻辑内聚到Fragment中,可添加可见状态标记位判断:
class InboxFragment : Fragment() { private var isVisibleToUser = false override fun onResume() { super.onResume() // ViewPager2搭配FragmentStateAdapter时,仅选中的Fragment会走到RESUMED状态 isVisibleToUser = true } override fun onPause() { // 仅当前Fragment对用户可见时才执行标记逻辑 if (isVisibleToUser) { inboxViewModel.markNotificationsAsRead(arguments?.getInt(CURRENT_TAB, -1) ?: 0) isVisibleToUser = false } super.onPause() } }
原实现问题说明
原写法没有判断Fragment是否对用户真实可见,ViewPager2的预加载机制会提前初始化相邻Tab的Fragment,Activity销毁时所有已初始化的Fragment都会执行onPause生命周期,导致未展示的Tab也触发了已读标记逻辑。
内容的提问来源于stack exchange,提问作者Kartik
相关产品推荐
相关产品推荐

