问题描述
尝试使用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使用击键 ActivityRetainedComponent是整体的,因此任何@ViewModelInject 您的DFM中的班级不会被识别。
到目前为止,似乎不可能仅在动态要素模块中使用@ViewModelInject
和by 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)
}
}