shashwat
shashwat

Reputation: 59

How to use dependency injection for injecting constructor in a ViewModel

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.

Upvotes: 4

Views: 3738

Answers (2)

Pratik Mhatre
Pratik Mhatre

Reputation: 779

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

Upvotes: 1

Francis
Francis

Reputation: 7104

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

Upvotes: 0

Related Questions