我如何在模块中添加视图模型?

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