首页 > 解决方案 > 在 Android 上的视图模型中使用 Dagger 2 单例

问题描述

我希望我的应用程序具有以下架构:

-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

在 Android 上,人们似乎通常在活动中进行依赖注入,但我想在视图模型中注入我的存储库。

我有一个使用手动创建的 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)
    }

}

在我的 RoomModule 中,我有这个提供者:

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

DisplayScreenDataSource 类非常简单:

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

我希望这个单例可用于其他视图模型 MainActivityViewModel,所以我这样做了:

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

    @Inject
    lateinit var displayScreenRepository: DisplayScreenRepository


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

但是当我运行我的应用程序时,实例化的存储库没有相同的引用,并且当我在我的一个 ViewModel 中更新一个 LiveData 的值时,如果我观察到另一个 ViewModel 的 LiveData,它不是同一个 LiveData 所以是没有更新。

我的猜测是我没有正确实例化 DaggerAppComponent :它应该只创建一次并最终注入几次。那正确吗?

我应该在哪里存储 DaggerAppComponent 的实例?在应用程序类中?

我可以有这样的东西:

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

    @Inject
    lateinit var displayScreenRepository: DisplayScreenRepository


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

这是推荐的方式吗?

标签: androidkotlindagger-2android-viewmodel

解决方案


推荐阅读