【问题标题】:Android ViewPager2 how to retrieve the fragment onBindViewHolderAndroid ViewPager2如何检索片段onBindViewHolder
【发布时间】:2020-04-13 13:54:29
【问题描述】:

ViewPager 发布 1.0.0 版本

对于普通的 RecyclerView,holder.itemView 为我提供当前绑定/呈现的视图。

但是,FragmentStateAdapter 的 holder.itemView 只给了我一个 FrameLayout

我的 ViewPager 适配器:

class MyFragmentStateAdapter(activity: FragmentActivity) :
    FragmentStateAdapter(activity) {
    var items = mutableListOf<String>()
    override fun createFragment(position: Int): MyPageFragment {
        val itemText = items[position]
        return MyPageFragment.create(itemText)
    }

    override fun getItemCount(): Int = items.size

    override fun onBindViewHolder(
        holder: FragmentViewHolder,
        position: Int,
        payloads: MutableList<Any>
    ) {
        super.onBindViewHolder(holder, position, payloads)
        val fragment = ??? as MyRefreshableInterface
        fragment.refresh()
    }

    fun update(mutableListOf: MutableList<String>) {
        this.items = mutableListOf
        notifyDataSetChanged()
    }
}

上下文

我有少量且固定数量的选项卡显示用户配置文件的不同信息部分。在某些事件中,我需要尽快自动刷新所有选项卡。换句话说,除了用户正在查看的当前选项卡之外,我还需要刷新当前隐藏的选项卡。

ASAP = 用户下次访问当前隐藏的标签时。用户去那里,他们首先看到的是加载动画。挺好的

为什么不马上?

因为隐藏的碎片可能会被分离/破坏。无论如何,用户现在没有在看。将所有碎片都保存在内存中也很昂贵

当用户导航到上一个隐藏选项卡说 地址onBindViewHolder 将被触发(这与 ViewPager 1 相比很棒)但是,差距是我没有参考当前选择的片段

其他发现

我已经尝试引用 fragmentActivity.supportFragmentManager.fragments,但它似乎最多有 4 个片段,而我有 6 个片段/页面,为了测试

【问题讨论】:

    标签: android android-fragments android-viewpager android-fragmentactivity android-viewpager2


    【解决方案1】:

    您似乎在问两个不同的问题。

    我需要自动刷新所有选项卡。换句话说,除了用户正在查看的当前选项卡之外,我还需要刷新当前隐藏的选项卡。

    当用户导航到上一个隐藏选项卡说地址时,将触发 onBindViewHolder。

    当显示在第二个项目上时,您正在尝试进行更新。


    使用 viewpager2 可以轻松实现“显示时更新”,当显示 Fragment 时,Fragment 会从“Started”进入生命周期状态“Resumed”。

    因此在每个Fragment中创建一个update方法,然后在Fragments的onResume方法中调用update方法。

    (这是我在我的应用程序中所做的)

    更新:
    关于这种行为的文档在 viewpager2 中很糟糕,我能找到的最好的是源代码中的注释 https://android.googlesource.com/platform/frameworks/support/+/refs/heads/androidx-master-dev/viewpager2/viewpager2/src/main/java/androidx/viewpager2/adapter/FragmentStateAdapter.java#634

    /** *暂停(开始)所有附加的片段,而不是主要项目。 * 保持主要项目片段恢复。 */

    或发布说明https://developer.android.com/jetpack/androidx/releases/viewpager2#1.0.0-alpha06

    FragmentStateAdapter:非主要项目 Fragments 的上限为 STARTED,并且它们的 menuVisibility 设置为 false。

    Androidx 中的 Viewpager 1 已更新为 BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT 以匹配 Viewpager2 的行为 见https://developer.android.com/reference/androidx/fragment/app/FragmentStatePagerAdapter#BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT


    “更新所有片段”有点难,但我相信您可以执行以下操作(抱歉,我的 Kotlin 无法提供代码示例。

    在适配器构造函数中创建并存储片段列表(不仅仅是 itemText)
    例如项目中的 foreach 项目添加到片段列表 MyPageFragment.create(itemText)

    然后在createFragment 中只需从列表的正确位置返回片段。
    例如return fragments[position]

    然后在您的适配器update 中迭代您的片段列表中的所有项目,并在每个片段上调用update

    (这基本上是在适配器中维护您自己的片段列表,而不是在调用createFragment 时动态创建它们)

    更新:
    正如 cmets 中指出的那样,这不太理想并且打破了 Viewpager2 的 Fragment 生命周期概念和效率,Fragment 的onResume 中的更新更好。

    【讨论】:

    • 在 ViewPager 1 中,onResume 通常不会被调用。你能指出我说onResume将在ViewPager2中被调用的文档吗? 在适配器构造器中创建和存储片段列表既昂贵又脆弱
    • 所以文档在这方面很糟糕,但是如果您查看发行说明developer.android.com/jetpack/androidx/releases/…“FragmentStateAdapter:非主要项目片段的上限为 STARTED,并且它们的 menuVisibility 设置为 false。” viewpager1 也已更新以匹配此行为,并有更好的文档记录参见 developer.android.com/reference/androidx/fragment/app/…BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT
    • Viewpager1 用于将所有片段提升到 Resumed,但在 Androidx 中已被弃用,因为它破坏了生命周期概念,BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT 是唯一的选项,因为它与 viewpager2 的行为匹配。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-30
    • 1970-01-01
    • 2021-01-12
    相关资源
    最近更新 更多