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

Inject Application Context in Repository with Dagger 2

我使用 Dagger 2.17 获取存储库中的应用程序上下文以访问资源:

ContextInjection.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:

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:

@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:

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

这有效,但我有下一个 问题: 有没有其他(更好的)方法可以使用 Dagger 获取存储库中的上下文?

注意: 我对静态调用感到困惑:

context = Initialization.contextComponent.inject()

不确定这是否是好的做法。

感谢您的任何 answer/comment!

您可以使用向存储库提供这些资产的依赖项。并且这种依赖关系可以包含对上下文的引用。因此您的存储库可以简单地查询此依赖项以获取所需的资产。

要点如下:

资产提供者:

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

存储库:

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

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

我喜欢拥有对 Android 特定内容的依赖性最小的存储库。因此,存储库逻辑与其运行的平台无关。这也有助于单元测试,您不必注入上下文来测试您的存储库。