如何使用Dagger-Hilt在动态特征模块中创建ViewModel



尝试在具有private val viewModel: PostDetailViewModel by viewModels()的动态功能模块中创建ViewModel

片段

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并从应用程序模块获取它们吗?

基于此官方github发布

Hilt和DFM的文档现在在https://developer.android.com/training/dependency-injection/hilt-multi-module#dfm

但总的来说,因为我们是由子组件和单片组件,您将无法使用标准Hilt使用DFM的@AndroidEntryPoint等机制。

不幸的是,没有。@ViewModelInject使用HiltActivityRetainedComponent是单片的,因此任何@ViewModelInjectDFM中的类将不会被识别。

到目前为止,在动态功能模块中仅使用@ViewModelInjectby viewModels()注入ViewModel似乎是不可能的。

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

@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是

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
}
}

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

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)
}
}

最新更新