Внедрить контекст приложения в репозиторий с помощью Dagger 2 - PullRequest
0 голосов
/ 01 августа 2020

Я использовал 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?

Примечание : меня смущает stati c invoke:

context = Initialization.contextComponent.inject()

Не уверен если это хорошая практика.

Спасибо за любой ответ / комментарий!

1 Ответ

1 голос
/ 01 августа 2020

Вы можете использовать зависимость, которая предоставляет эти активы в репозиторий. И эта зависимость может содержать ссылку на контекст. Таким образом, ваш репозиторий может просто запросить эту зависимость, чтобы получить требуемые ресурсы.

Вот его суть:

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 специфических c вещей. Итак, logi c репозитория зависит от c платформы, на которой он работает. Это также помогает в модульных тестах, где вам не нужно вводить контекст для тестирования вашего репозитория.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...