How i can add view model in module?

时光怂恿深爱的人放手 提交于 2020-06-29 05:26:15

问题


In Dagger, how can I add a model to Module? For example I added the presenter in the following way:

@Module
class AboutModule(val appContext: Context) {

    @FragmentScope
    @Provides
    fun providePresenter(): AboutListContract.Presenter {
        return AboutListPresenter(appContext = appContext)
    }
}

Now i want want to add my View model, also with appContext.

class AboutViewModel(val appContext: Context): ViewModel() {

UPDATE: Can i add my view model smth like this?

@Module

    class AboutModule(val appContext: Context) {

        @FragmentScope
        @Provides
        fun provideModel(model: AboutViewModel): ViewModel {
            return AboutViewModel(appContext = appContext)
        }
    }

回答1:


I solved my problem with next solution:

@Module
class AboutModule(val appContext: Context) {

    @FragmentScope
    @Provides
    fun provideFactory(): AboutViewModelFactory {
        return AboutViewModelFactory(appContext)
    }
}

And in fragment write smth like this: 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)
    }
}

Nice advise: https://stackoverflow.com/a/60884492/6387618




回答2:


To retrieve the ViewModel from the component without Map Multibinding, you can do:

@Singleton
@Component(modules=[...])
interface SingletonComponent {
    val aboutListViewModel: Provider<AboutListViewModel>
}

Which works when you can use @Inject constructor:

// unscoped
class AboutListViewModel @Inject constructor(): ViewModel() {
}

Because now you can do:

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

Which might seem tacky, but you can hide all of that in an extension function

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

Because now you can do

class AboutListFragment: Fragment(R.layout.about_list_fragment) {
    private val viewModel by fragmentViewModels<AboutListViewModel> { component ->
        component.aboutListViewModel().get()
    }
}

And this would work even without map multibinding. If you need a SavedStateHandle, you'd need AssistedInject, but if you don't want that, it'll be easier when Dagger-Hilt is stable (then it'll be as simple as @ViewModelInject and @Assisted).




回答3:


ViewModels are injected using Dagger Multibindings

refer to this medium article: https://medium.com/chili-labs/android-viewmodel-injection-with-dagger-f0061d3402ff

context can be injected by providing in the AppModule class.



来源:https://stackoverflow.com/questions/60884402/how-i-can-add-view-model-in-module

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!