我如何在模块中添加视图模型?
How i can add view model in module?
在 Dagger 中,如何将模型添加到模块中?
例如,我通过以下方式添加了演示者:
@Module
class AboutModule(val appContext: Context) {
@FragmentScope
@Provides
fun providePresenter(): AboutListContract.Presenter {
return AboutListPresenter(appContext = appContext)
}
}
现在我想添加我的视图模型,还有 appContext。
class AboutViewModel(val appContext: Context): ViewModel() {
更新:
我可以像这样添加我的视图模型吗?
@Module
class AboutModule(val appContext: Context) {
@FragmentScope
@Provides
fun provideModel(model: AboutViewModel): ViewModel {
return AboutViewModel(appContext = appContext)
}
}
ViewModels 使用 Dagger 注入 Multibindings
参考这篇中篇文章:
https://medium.com/chili-labs/android-viewmodel-injection-with-dagger-f0061d3402ff
context
可以通过在 AppModule class.
中提供来注入
我用下一个解决方案解决了我的问题:
@Module
class AboutModule(val appContext: Context) {
@FragmentScope
@Provides
fun provideFactory(): AboutViewModelFactory {
return AboutViewModelFactory(appContext)
}
}
然后在片段中这样写:
class AboutFragment : BaseFragment(), OnItemClickListener {
lateinit var viewModel: AboutViewModel
@Inject lateinit var viewModelFactory: AboutViewModelFactory
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
injectDependencies()
viewModel = ViewModelProviders
.of(this, viewModelFactory)
.get(AboutViewModel::class.java)
}
private fun injectDependencies() {
activity?.let {
DaggerAboutComponent.builder().aboutModule(AboutModule(it)).build().inject(this)
}
}
很好的建议:
要在没有 Map Multibinding 的情况下从组件中检索 ViewModel,您可以这样做:
@Singleton
@Component(modules=[...])
interface SingletonComponent {
val aboutListViewModel: Provider<AboutListViewModel>
}
当您可以使用 @Inject constructor
:
时哪个有效
// unscoped
class AboutListViewModel @Inject constructor(): ViewModel() {
}
因为现在你可以做:
class AboutListFragment: Fragment(R.layout.about_list_fragment) {
private val viewModel by viewModels<AboutListViewModel>() {
object: ViewModelProvider.Factory {
override fun create(clazz: Class<ViewModel>) {
return (requireActivity().application as MyApplication).component.aboutListViewModel.get()
}
}
}
}
这可能看起来俗气,但您可以将所有这些隐藏在扩展函数中
fun <T: ViewModel> Fragment.fragmentViewModels(viewModelCreator: SingletonComponent.() -> T) = viewModels<T> {
object: ViewModelProvider.Factory {
override fun create(clazz: Class<ViewModel>) {
val component = requireActivity().application as MyApplication).component
return viewModelCreator(component)
}
}
}
因为现在你可以做到
class AboutListFragment: Fragment(R.layout.about_list_fragment) {
private val viewModel by fragmentViewModels<AboutListViewModel> { component ->
component.aboutListViewModel().get()
}
}
即使没有地图多重绑定,这也能正常工作。如果你需要 SavedStateHandle
,你需要 AssistedInject,但如果你不想那样,当 Dagger-Hilt 稳定时它会更容易(然后它会像 @ViewModelInject
一样简单和 @Assisted
).
在 Dagger 中,如何将模型添加到模块中? 例如,我通过以下方式添加了演示者:
@Module
class AboutModule(val appContext: Context) {
@FragmentScope
@Provides
fun providePresenter(): AboutListContract.Presenter {
return AboutListPresenter(appContext = appContext)
}
}
现在我想添加我的视图模型,还有 appContext。
class AboutViewModel(val appContext: Context): ViewModel() {
更新: 我可以像这样添加我的视图模型吗?
@Module
class AboutModule(val appContext: Context) {
@FragmentScope
@Provides
fun provideModel(model: AboutViewModel): ViewModel {
return AboutViewModel(appContext = appContext)
}
}
ViewModels 使用 Dagger 注入 Multibindings
参考这篇中篇文章: https://medium.com/chili-labs/android-viewmodel-injection-with-dagger-f0061d3402ff
context
可以通过在 AppModule class.
我用下一个解决方案解决了我的问题:
@Module
class AboutModule(val appContext: Context) {
@FragmentScope
@Provides
fun provideFactory(): AboutViewModelFactory {
return AboutViewModelFactory(appContext)
}
}
然后在片段中这样写: class AboutFragment : BaseFragment(), OnItemClickListener {
lateinit var viewModel: AboutViewModel
@Inject lateinit var viewModelFactory: AboutViewModelFactory
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
injectDependencies()
viewModel = ViewModelProviders
.of(this, viewModelFactory)
.get(AboutViewModel::class.java)
}
private fun injectDependencies() {
activity?.let {
DaggerAboutComponent.builder().aboutModule(AboutModule(it)).build().inject(this)
}
}
很好的建议:
要在没有 Map Multibinding 的情况下从组件中检索 ViewModel,您可以这样做:
@Singleton
@Component(modules=[...])
interface SingletonComponent {
val aboutListViewModel: Provider<AboutListViewModel>
}
当您可以使用 @Inject constructor
:
// unscoped
class AboutListViewModel @Inject constructor(): ViewModel() {
}
因为现在你可以做:
class AboutListFragment: Fragment(R.layout.about_list_fragment) {
private val viewModel by viewModels<AboutListViewModel>() {
object: ViewModelProvider.Factory {
override fun create(clazz: Class<ViewModel>) {
return (requireActivity().application as MyApplication).component.aboutListViewModel.get()
}
}
}
}
这可能看起来俗气,但您可以将所有这些隐藏在扩展函数中
fun <T: ViewModel> Fragment.fragmentViewModels(viewModelCreator: SingletonComponent.() -> T) = viewModels<T> {
object: ViewModelProvider.Factory {
override fun create(clazz: Class<ViewModel>) {
val component = requireActivity().application as MyApplication).component
return viewModelCreator(component)
}
}
}
因为现在你可以做到
class AboutListFragment: Fragment(R.layout.about_list_fragment) {
private val viewModel by fragmentViewModels<AboutListViewModel> { component ->
component.aboutListViewModel().get()
}
}
即使没有地图多重绑定,这也能正常工作。如果你需要 SavedStateHandle
,你需要 AssistedInject,但如果你不想那样,当 Dagger-Hilt 稳定时它会更容易(然后它会像 @ViewModelInject
一样简单和 @Assisted
).