I used the Dagger 2.17 to get the application context in the repository to access the resources:
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
}
}
This works, but I have the next question: is there any other (better) way to get the context in the repository using a Dagger?
Note: I am confused by the static invoke:
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. 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.