如何使用Dagger Hilt在动态要素模块中创建ViewModel? [英] How to create ViewModel in dynamic feature module with Dagger Hilt?

查看:139
本文介绍了如何使用Dagger Hilt在动态要素模块中创建ViewModel?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尝试在具有动态代码模块的私有代码中创建ViewModel私有val viewModel:viewModels()通过PostModelViewModel()

Trying to create ViewModel in a dynamic feature module with private val viewModel: PostDetailViewModel by viewModels()

片段

class PostDetailFragment : DynamicNavigationFragment<FragmentPostDetailBinding>() {

    private val viewModel: PostDetailViewModel by viewModels()
    
    override fun getLayoutRes(): Int = R.layout.fragment_post_detail

    override fun bindViews() {
        // Get Post from navigation component arguments
        val post = arguments?.get("post") as Post
        dataBinding.item = post
        viewModel.updatePostStatus(post)
        
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        initCoreDependentInjection()
        super.onCreate(savedInstanceState)
    }

    private fun initCoreDependentInjection() {

        val coreModuleDependencies = EntryPointAccessors.fromApplication(
            requireActivity().applicationContext,
            DomainModuleDependencies::class.java
        )

        DaggerPostDetailComponent.factory().create(
            coreModuleDependencies,
            requireActivity().application
        )
            .inject(this)

    }
}

结果错误

Caused by: java.lang.InstantiationException: java.lang.Class<com.x.post_detail.PostDetailViewModel> has no zero argument constructor

它可以在应用模块中的任何片段中工作,但不能在动态功能模块中工作.将ViewModels添加到动态要素模块的正确方法是什么?我应该使用ViewModelFactory在应用程序模块中创建ViewModels并从应用程序模块中获取它们吗?

it works in any fragment in app module but not working in dynamic feature modules. What's the proper way to add ViewModels to dynamic feature modules? Should i create ViewModels in app module with a ViewModelFactory and get them from app module?

推荐答案

基于此官方 github帖子

现在可以在以下位置找到有关Hilt和DFM的文档 https://developer.android.com/training/dependency-注射/hilt-multi-module#dfm

通常,因为我们是基于子组件和整体组件,您将无法使用标准的Hilt带有DFM的@AndroidEntryPoint之类的机制.

In general though, because we're built off of subcomponents and monolithic components you won't be able to use the standard Hilt mechanisms like @AndroidEntryPoint with DFM.

不幸的是,没有.@ViewModelInject使用击键ActivityRetainedComponent是整体的,因此任何@ViewModelInject您的DFM中的班级不会被识别.

Unfortunately, no. @ViewModelInject uses the Hilt ActivityRetainedComponent which is monolithic, so any @ViewModelInject class in your DFM won't be recognized.

目前看来,仅不可能通过动态特征模块中的viewModels()和 @ViewModelInject 注入ViewModel.

it seems that injecting to a ViewModel only with @ViewModelInject and by viewModels() in a dynamic feature module is not possible as of now.

基于格子应用程序,我将动态功能模块中的Dagger模块重建为

Based on plaid app i rebuilt my Dagger module in dynamic feature module as

@InstallIn(FragmentComponent::class)
@Module
class PostDetailModule {

    @Provides
    fun providePostDetailViewModel(fragment: Fragment, factory: PostDetailViewModelFactory) =
        ViewModelProvider(fragment, factory).get(PostDetailViewModel::class.java)

    @Provides
    fun provideCoroutineScope() = CoroutineScope(Dispatchers.Main.immediate + SupervisorJob())

}

ViewModel和ViewModelFactory是

And ViewModel and ViewModelFactory are

class PostDetailViewModel @ViewModelInject constructor(
    private val coroutineScope: CoroutineScope,
    private val getPostsUseCase: UseCase
) : ViewModel() {
 
    // Do other things
}

class PostDetailViewModelFactory @Inject constructor(
    private val coroutineScope: CoroutineScope,
    private val getPostsUseCase: UseCase
) : ViewModelProvider.Factory {

    @Suppress("UNCHECKED_CAST")
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        if (modelClass != PostDetailViewModel::class.java) {
            throw IllegalArgumentException("Unknown ViewModel class")
        }
        return PostDetailViewModel(
            coroutineScope,
            getPostsUseCase
        ) as T
    }
}

并注入动态特征模块中的片段

And injected to fragment in dynamic feature module

class PostDetailFragment : Fragment() {

    @Inject
    lateinit var viewModel: PostDetailViewModel


    override fun onCreate(savedInstanceState: Bundle?) {
        initCoreDependentInjection()
        super.onCreate(savedInstanceState)
    }

    private fun initCoreDependentInjection() {

        val coreModuleDependencies = EntryPointAccessors.fromApplication(
            requireActivity().applicationContext,
            DomainModuleDependencies::class.java
        )

        DaggerPostDetailComponent.factory().create(
            dependentModule = coreModuleDependencies,
            fragment = this
        )
            .inject(this)
    }
}

这篇关于如何使用Dagger Hilt在动态要素模块中创建ViewModel?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆