How to use dependency injection for injecting constructor in a ViewModel

做~自己de王妃 提交于 2019-11-27 06:24:10

问题


I am trying to implement the example on https://developer.android.com/jetpack/docs/guide. This explains how tan android app should be structured.

When I use the same code, I get following error.

java.lang.Class<com.example.UserProfileViewModel> has no zero argument constructor

I could figure out that this error has something to do with

viewModel = ViewModelProviders.of(this).get(UserProfileViewModel.class);

When I write a default zero input constructor for ViewModel I get the following error.

Attempt to invoke virtual method 'void android.arch.lifecycle.LiveData.observe(android.arch.lifecycle.LifecycleOwner, android.arch.lifecycle.Observer)' on a null object reference

I can not figure out the reason for this error and how to solve it.


回答1:


If you want to provide viewmodel with constructor as a dependency in your Fragment, there is a different method for it,

Lets suppose you have a viewmodel class as belows,

class SampleViewmModel(dataManager:DataManager):ViewModel(){
  //some logic
}

Then you will need to create a factory class to support above viewmodel like below,

class SampleFactory @Inject constructor(var dataManager:DataManager): ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
    if (modelClass.isAssignableFrom(SampleViewModel::class)) {
        return SampleViewModel(dataManager) as T
    }
    throw IllegalStateException()
}

}

Now in your module class, you can inject above classes as below, (Note-Datamanager class is injectible)

//Provide Factory
@Provides
fun provideFactory(dataManager:DataManager): SampleFactory {
    return SampleFactory(dataManager)
}

//Provide actual viewmodel
@Provides
fun provideViewModel(sampleFactory: SampleFactory): SampleViewModel {
    return ViewModelProviders.of(fragment, sampleFactory)[SampleViewModel::class]
}

No in your Fragment, you can inject your viewmodel just like any other dependency,

@Injetct
lateinit viewModel:SampleViewModel



回答2:


You can use Koin as an alternative for Dagger. Koin have full support of Android Architecture ViewModel. It's extremely easy to use. I prefer it for small and mid-sized project.

// declared ViewModel using the viewModel keyword
val myModule : Module = module {
    viewModel { MyViewModel(get()) } 
    ...
}

// Just get it
class MyActivity() : AppCompatActivity() {

    // lazy inject MyViewModel
    val myViewModel : MyViewModel by viewModel()
}

insert-koin.io



来源:https://stackoverflow.com/questions/50949221/how-to-use-dependency-injection-for-injecting-constructor-in-a-viewmodel

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