如何将 FragmentFactory 与 FragmentStatePagerAdapter 一起使用
Posted
技术标签:
【中文标题】如何将 FragmentFactory 与 FragmentStatePagerAdapter 一起使用【英文标题】:How can I use FragmentFactory with FragmentStatePagerAdapter 【发布时间】:2020-09-15 12:57:41 【问题描述】:我喜欢FragmentFactory
的方法,它可以将依赖项传递给构造函数中的片段。
我想同时使用自定义 FragmentFactory
和 FragmentStatePagerAdapter
。
我在活动中托管视图寻呼机。我可以创建一个自定义片段工厂并将其分配给活动使用
supportFragmentManager.fragmentFactory = CustomFragmentFactory()
然后我可以使用supportFragmentManager
来初始化我的FragmentStatePagerAdapter
。
到目前为止还不错。
我的问题是视图寻呼机中的片段显示的数据取决于位置。
假设我有一个列表items
和ItemFragment
,它显示在显示items[position]
的视图寻呼机中,因此有一个这样的构造函数:
class ItemFragment(val item: Item) : Fragment()
我必须如何实现CustomFragmentFactory
和FragmentStatePagerAdapter
的getItem(position: Int)
函数才能实现安全等效:
override fun getItem(position: Int) = ItemFragment(items[position])
【问题讨论】:
您找到解决方案了吗?我面临同样的问题.. 不幸的是,没有。我根本没有使用FragmentFactory
方法,而是坚持使用使用Bundle
传递参数的空构造函数片段的传统方法。
【参考方案1】:
首先,现在不推荐使用 FragmentStatePagerAdapter。因此,最好将 FragmentStateAdapter 与 ViewPager2 一起使用。
如果您需要使用 ViewPager2 将某些内容传递给 Fragment 的构造函数,我找不到任何合适的解决方案,因为它忽略了 FragmentFactory。我正在考虑在 FragmentStateAdapter 的 createFragment 方法中实现 FragmentFactory,但不知道在这种情况下从哪里获得正确的类加载器。
我找到的唯一解决方案是使用 FragmentManager.FragmentLifecycleCallbacks。在这里,您有一个片段,因此您可以将其转换为您的特定实现。您可以在片段(重新)创建后设置回调或任何您想要的片段。所以在这种情况下,你不需要向片段的构造函数传递一些东西,但也可以避免创建 Bundle。
fragmentManager?.registerFragmentLifecycleCallbacks(object : FragmentManager.FragmentLifecycleCallbacks()
override fun onFragmentPreCreated(fm: FragmentManager, f: Fragment, savedInstanceState: Bundle?)
super.onFragmentPreCreated(fm, f, savedInstanceState)
, true)
我使用 childFragmentManager 测试了这段代码,它运行良好。但我不得不承认,这不是一个明确的解决方案。如果您可以避免在使用 FragmentStateAdapter 时将某些内容传递给 Fragment 的构造函数,请避免使用它。因为最合适的解决方案是使用 FragmentFactory。
另外,作为一个选项,您的片段知道父 Activity。因此,您可以直接对父 Activity 进行回调。
文档链接:https://developer.android.com/reference/androidx/fragment/app/FragmentManager#registerFragmentLifecycleCallbacks(androidx.fragment.app.FragmentManager.FragmentLifecycleCallbacks,%20boolean)
【讨论】:
我认为我们同意FragmentFactory
在这里不适用。我个人不会使用生命周期回调方法为片段设置参数,因为对Fragment
进行实例检查的需求似乎很脆弱。对于传递参数,我会将代码保留在片段中,并且也靠近构造函数调用,例如通过使用 newInstance 模式 (medium.com/@azjkjensen/…) 或 Safe Args。
@PeterF 是的,我完全同意你的看法。我只是提供了一种方法,如果有必要,它可能是如何完成的。由于 FragmentStateAdapter 不适用于片段工厂,因此某些需要回调的模式无法在此处应用。此外,我完全同意在这种情况下进行类转换并不是解决问题的非常明确的方法。而且,正如我所说,如果可以避免这种解决方案,那就避免吧:)【参考方案2】:
FragmentFactory
不提供传递动态数据的方法。因此,FragmentFactory
在这种情况下不起作用。
如果您有动态参数,则必须使用捆绑包以经典方式传递它们(或使用像 Safe Args 这样的方法,它使用捆绑包生成代码)。
This article 谈到了完全相同的场景:
使用 FragmentFactory 的限制是我们不能将动态参数传递给它。
假设我们有一个 ViewPager,它显示相同 mainFragment 的两个实例,但具有不同的 textToDisplay 值,那么使用 fragmentFactory 实现将无法实现。
【讨论】:
以上是关于如何将 FragmentFactory 与 FragmentStatePagerAdapter 一起使用的主要内容,如果未能解决你的问题,请参考以下文章
FragmentFactory + Koin 实现Fragment依赖注入
Oracle中,如何查看FRA(Flashback Recovery Area)的利用率