如何在销毁活动之前在视图寻呼机内的片段中执行某些操作
Posted
技术标签:
【中文标题】如何在销毁活动之前在视图寻呼机内的片段中执行某些操作【英文标题】:How to perform certain operations in a fragment inside a view pager before the activity is destroyed 【发布时间】:2021-12-29 01:33:16 【问题描述】:我的活动布局如下
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_
android:orientation="vertical"
android:id="@+id/fragment_container"
android:layout_>
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewpager"
android:layout_
android:layout_>
<com.google.android.material.tabs.TabLayout
android:id="@+id/inbox_tab"
android:layout_
android:layout_
style="@style/TabLayoutStyle"
/>
</androidx.viewpager2.widget.ViewPager2>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
适配器如下所示
class InboxAdapter(fragment: Fragment) : FragmentStateAdapter(fragment)
override fun getItemCount(): Int = 2
override fun createFragment(position: Int): Fragment =
InboxFragment().apply
arguments = Bundle().apply
// Our object is just an integer :-P
putInt(InboxFragment.CURRENT_TAB, position)
片段布局由一个在onCreateView
方法中创建和初始化的回收器视图组成。
<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_
android:layout_
app:layoutManager="LinearLayoutManager"/>
我的活动调用 API 端点以获取两组列表,表示已读和未读通知的组合,每一个都填充在特定片段的回收器视图中。
活动将值存储在两组实时数据实例中,并在two fragments like the tutorial suggests 之间传递数据。这很好用。
问题
我必须向后端发送一个 PUT 请求,其中请求正文包含当前在前台的片段的未读通知列表。
-
当用户切换标签时
当用户离开屏幕时
对于第一个选项,我可以在我的片段中执行如下操作:
override fun onPause()
// Aggregates the list of unread notifications, and submits a PUT request.
// Updates the view model live data backing list as well to mark as read.
// View Model is initialised as per the tutorial
inboxViewModel.markNotificationsAsRead(arguments?.getInt(CURRENT_TAB, -1) ?: 0)
super.onPause()
当用户离开屏幕时,第二个用例会失败,从而破坏活动。在这种情况下,两个片段都会在它们的视图被销毁之前暂停。这会导致两个列表中的两个未读通知都被标记为已读。
考虑用户在第一个片段(默认加载)上的用例,然后离开收件箱屏幕导航到由另一个活动管理的另一个屏幕,然后我只希望显示未读通知第一个片段被标记为已读。
由于未加载第二个片段,因此不应将本应显示在第二个片段中的未读通知标记为已读。
我怎样才能做到这一点?
【问题讨论】:
为什么不在用户点击通知后立即将它们标记为已读? 我们也对点击进行此操作,但在这种特定情况下,我们希望在用户离开屏幕时将其标记为已读。 只是为了澄清这不是推送通知,而是类似电子邮件的收件箱屏幕。 【参考方案1】:当片段可见时将消息标记为已读。所以在Activity销毁的时候不需要标记消息是否被读取。
或者在片段中添加一个公共字段来标记片段是否已显示。然后根据这个标签调用inboxViewModel.markNotificationsAsRead
。
How to determine if the fragment is displayed
------------------------------------20210-11-12------ ------------------ 演示代码sn-p
interface ICheckFragment
fun markShown()
fun hasShown(): Boolean
// in your adapter
xxxAdapter: FragmentPagerAdapter(fm)
private val fragments = mutableListOf<Fragment>()
init
val fragment = PlaceholderFragment.newInstance(1)
val fragment2 = PlaceholderFragment.newInstance(2)
fragments.add(fragment)
fragments.add(fragment2)
override fun getItem(position: Int): Fragment
return fragments[position]
// in your activity code
tabs.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener
// Please notice that this callback not be called at first when viewpager shown.
// You need mark fragment at position 0 shown manually
override fun onTabSelected(tab: TabLayout.Tab?)
val position = tab?.position ?: 0
val fragment = sectionsPagerAdapter.getItem(position)
if (fragment is ICheckFragment)
fragment.markShown()
override fun onTabUnselected(tab: TabLayout.Tab?) = Unit
override fun onTabReselected(tab: TabLayout.Tab?) = Unit
)
val fragment0 = sectionsPagerAdapter.getItem(0)
if (fragment is ICheckFragment)
fragment.markShown()
// in your fragment
class xxxFragment: Fragment(), ICheckFragment
...
private var hasShown = false
override fun markShown()
hasShown = true
override fun hasShown(): Boolean
return hasShown
override fun onPause()
super.onPause()
// do your logic
if (hasShown)
else
【讨论】:
两个原因:1. 无法区分新旧通知。 2. 建议的解决方案已在 AndroidX 片段中弃用。 developer.android.com/reference/androidx/fragment/app/… @Kartik 监控TabLayout的onTabSelected事件如何,然后设置是否显示Fragment 您介意粘贴代码 sn-p, @Kartik 我用演示代码 sn-p 更新了我的答案。 @leimenghao 你可以看看这个issue以上是关于如何在销毁活动之前在视图寻呼机内的片段中执行某些操作的主要内容,如果未能解决你的问题,请参考以下文章