我使用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()
不确定这是否是一种好习惯。
谢谢您的任何回答/评论!
答案 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特定内容的依赖性最小的存储库。因此,存储库逻辑与其运行的平台无关。这也有助于进行单元测试,而您无需注入上下文即可测试存储库。