简体   繁体   English

使用 Dagger 2 在存储库中注入应用程序上下文

[英]Inject Application Context in Repository with Dagger 2

I used the Dagger 2.17 to get the application context in the repository to access the resources:我使用 Dagger 2.17 获取存储库中的应用程序上下文以访问资源:

ContextInjection.kt:上下文注入.kt:

@Module
class ContextModule(private val context: Context) {

    @Singleton
    @Provides
    fun providesContext(): Context {
        return context
    }
}

@Singleton
@Component(modules = [ContextModule::class])
interface ContextComponent {
    fun inject(): Context
}

Initialization.kt:初始化.kt:

class Initialization : Application() {

    override fun onCreate() {
        super.onCreate()

        contextComponent = DaggerContextComponent.builder()
            .contextModule(ContextModule(this.applicationContext))
            .build()
    }

    companion object { // for access in repository
        lateinit var contextComponent: ContextComponent
    }
}

Repository.kt:存储库.kt:

@Singleton
class Repository {

    @Inject
    lateinit var context: Context

    /** the method is invoked from view model class */
    fun loadList(pageIndex: Int): List<String> {
        context = Initialization.contextComponent.inject()
        val input = context.assets.open("tab1/item1/description.txt")
        ...
    }
}

ViewModel.kt: ViewModel.kt:

class PageViewModel : ViewModel() {

    @NonNull
    private val repository = Repository()

    private val pageIndex = MutableLiveData<Int>()

    val items = Transformations.map<Int, List<String>>(pageIndex) { index: Int ->
        repository.loadList(index)
    }

    fun setIndex(index: Int) {
        pageIndex.value = index
    } 
}

This works, but I have the next question : is there any other (better) way to get the context in the repository using a Dagger?这可行,但我有下一个问题:有没有其他(更好的)方法可以使用 Dagger 在存储库中获取上下文?

Note : I am confused by the static invoke:注意:我对 static 调用感到困惑:

context = Initialization.contextComponent.inject()

Not sure if this is good practice.不确定这是否是好习惯。

Thank you for any answer/comment!感谢您的任何回答/评论!

You can use a dependency which provides these assets to the repository.您可以使用将这些资产提供给存储库的依赖项。 And this dependency can contain a reference to the context.这个依赖可以包含对上下文的引用。 So your repository can simply query this dependency to get the assets it requires.因此,您的存储库可以简单地查询此依赖项以获取所需的资产。

Here's a gist of it:这是它的要点:

AssetProvider:资产提供者:

class AssetProvider @Inject constructor(
    private val context: Context
) {
    
    fun getDescription() = context.assets.open("tab1/item1/description.txt")
}

Repository:存储库:

@Singleton
class Repository @Inject constructor(
    private val assetProvider: AssetProvider
) {

    fun loadList(pageIndex: Int): List<String> {
        val input = assetProvider.getDescription()
        ...
    }
}

I like having repositories that have minimal dependency on Android specific stuff.我喜欢拥有对 Android 特定内容的依赖最小的存储库。 So the repository logic is agnostic to the platform it runs on.因此,存储库逻辑与其运行的平台无关。 This also helps in unit tests where you don't have to inject context to test your repository.这也有助于单元测试,您不必注入上下文来测试您的存储库。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM