首页 > 解决方案 > 如何将 ViewModelProvider.Factory 注入片段

问题描述

简而言之:如何将 ViewModelProvider.Factory 注入我的 Fragment 以访问适当的 ViewModel?

我有一个由 BottomNavigationBar 管理的选项卡的活动。每个选项卡屏幕都由一个片段表示。选项卡之间的切换是通过替换 Fragments 来完成的。

每个 TabFragment 都有一个关联的 ViewModel 类。这些 ViewModel 类在构造函数中接受参数,因此我必须创建一个 ViewModelProvider.Factory 来使用 ViewModelProvider。

自然,我的第一反应是在构建时将这个 Factory 注入到片段中,然后通过 ViewModelProvider 检索一个 ViewModel 实例:

class TabA(private val viewModelFactory: ViewModelProvider.Factory) : Fragment() {
    ...
    tabAViewModel = ViewModelProvider(this, viewModelFactory)
            .get(TabAViewmodel::class.java)
    ...
}

然而,片段需要无参数的构造函数。相反,可以通过静态工厂方法进行实例化,并且可以通过 Bundle 提供简单的参数,但似乎这个 Bundle 不能包含复杂类型,例如 ViewModelFactory。

然后如何将我的 ViewModelFactory 注入到 Fragment 中?片段是否可以进行自定义类型的依赖注入?

标签: androidandroid-fragmentsandroidx

解决方案


如果您想使用Fragment带有构造函数参数的 a,您可以使用FragmentFactory- 不再需要在片段上使用无参数构造函数。

  1. 创建可注射工厂:

     class MyFragmentFactory @Inject constructor(private val viewModelFactoryTabA: ViewModelProvider.Factory) : FragmentFactory() {
    
     override fun instantiate(classLoader: ClassLoader, className: String): Fragment =
         when (loadFragmentClass(classLoader, className)) {
             TabA::class.java     -> TabA(viewModelFactoryTabA)
             else                 -> super.instantiate(classLoader, className)
    
         }
    

    }

  2. 在父 Activity 中设置工厂:

     class MyActivity : AppCompatActivity() {
    
     @Inject lateinit var fragmentFactory: MyFragmentFactory
    
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
         supportFragmentManager.fragmentFactory = fragmentFactory
     }
    

    }

文档中的更多信息:https ://developer.android.com/reference/androidx/fragment/app/FragmentFactory


推荐阅读