Using Dagger 2 singletons in View Models on Android

Using Dagger 2 singletons in View Models on Android



I want my application to have the following architecture :


-di // dependancy injection package
-model
--datasources // implementations of repositories, using dao to return data
--dao // access to the database (room)
--repositories // interfaces
-ui // activities, fragments...
-viewmodels // viewmodels of each fragment / activity which will return data to the views in the ui package



On Android, people seem to usually have the dependancy injection in the activities, but I want to inject my repositories in view models.



I have one particular viewmodel that uses a manually created LiveData


class NavigationViewModel(application: Application) : AndroidViewModel(application)


init
DaggerAppComponent.builder()
.appModule(AppModule(getApplication()))
.roomModule(RoomModule(getApplication()))
.build()
.injectNavigationViewModel(this)


@Inject
lateinit var displayScreenRepository: DisplayScreenRepository

fun setScreenToDisplay(screen: DisplayScreen)
displayScreenRepository.setScreenToDisplay(screen)





In my RoomModule, I have this provider :


@Singleton
@Provides
internal fun displayScreenRepository(): DisplayScreenRepository
return DisplayScreenDataSource()



The class DisplayScreenDataSource is very simple :


class DisplayScreenDataSource : DisplayScreenRepository

private val screenToDisplay = MutableLiveData<DisplayScreen>()

override fun getScreenToDisplay(): LiveData<DisplayScreen>
return screenToDisplay


override fun setScreenToDisplay(screen: DisplayScreen)
if (Looper.myLooper() == Looper.getMainLooper())
screenToDisplay.value = screen
else
screenToDisplay.postValue(screen)





I want this singleton to be available to an other viewmodel, MainActivityViewModel, so I did this :


class MainActivityViewModel(application: Application) : AndroidViewModel(application)

@Inject
lateinit var displayScreenRepository: DisplayScreenRepository


init
DaggerAppComponent.builder()
.appModule(AppModule(application))
.roomModule(RoomModule(application))
.build()
.injectMainViewModel(this)




But when I run my application, the repositories instantiated don't have the same reference and when I update the value of one LiveData in one of my ViewModel, if I observe the LiveData of an other ViewModel, it is not the same LiveData so is is not updated.



My guess is that I am not correctly instantiating the DaggerAppComponent : it is supposed to be created only once and eventually injected several times.
Is that right?



Where should I be supposed to store the instance of the DaggerAppComponent? In the Application class?



I could have something like that :


class MainActivityViewModel(application: Application) : AndroidViewModel(application)

@Inject
lateinit var displayScreenRepository: DisplayScreenRepository


init
(application as MyApplication).daggerAppComponent.injectMainViewModel(this)




Is this the recommended way?





Please don't recreate your scoped components everywhere you use them. If you create 2x AppComponent then you have 2x your singletons, each component with their own instance. Create it once, then reuse it.
– David Medenjak
Aug 23 at 15:23





You should only have a single instance of AppComponent, otherwise you will create a new instance of everything you use each time
– EpicPandaForce
Aug 23 at 22:05


AppComponent





That's what I did in the end yes. I wondered where to put it, if there are some best practices, I have it in the application class at the moment.
– leb1755
Aug 24 at 6:53





I store it in the component it scopes / where I create it. ActivityComponents in activities, FragmentComponents in fragments, ServiceComponents in services. That's usually a safe bet
– David Medenjak
Aug 24 at 7:31









By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)