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

时间:2020-08-01 06:48:47

标签: android dependency-injection repository-pattern dagger-2 android-architecture-components

我使用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()

不确定这是否是一种好习惯。

谢谢您的任何回答/评论!

1 个答案:

答案 0 :(得分:1)

您可以使用将这些资产提供给资源库的依赖项。并且此依赖项可以包含对上下文的引用。因此,您的存储库只需查询此依赖关系即可获取所需的资产。

这是要点:

AssetProvider:

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特定内容的依赖性最小的存储库。因此,存储库逻辑与其运行的平台无关。这也有助于进行单元测试,而您无需注入上下文即可测试存储库。