Как правильно предоставить контекст для источника данных с чистой архитектурой, MVVM и Koin?

Я разрабатываю приложение для Android с Kotlin, в котором мне нужно получить текущее местоположение мобильного устройства. Я уже нашел способ сделать это в различных примерах, но я не знаю, как интегрировать эту логику в соответствии с чистой архитектурой с MVVM.

В моей архитектуре есть следующие уровни: презентация, прецедент, данные, домен и фреймворк. У меня есть уровень представления, организованный с помощью шаблона MVVM. Также я использую Koin для внедрения зависимостей.

Я получаю все данные, которые нужны моему приложению, из источников данных, находящихся на уровне Framework. Например, данные, полученные удаленно или из базы данных, или данные, предоставленные устройством (местом).

Вот пример файлов, участвующих в получении местоположения из ViewModel:

ConfigurationViewModel (уровень представления):

class ConfigurationViewModel(private val useCase: GetLocationUseCase) : ViewModel() {

    fun onSearchLocationButtonClicked() = liveData<Resource<Location>>(Dispatchers.IO) {
        emit(Resource.loading())
        try {
            emit(Resource.success(data = useCase.invoke(UseCase.None())))
        } catch (exception: Exception) {
            emit(Resource.error(message = exception.message))
        }
    }

GetLocationUseCase (уровень использования):

class GetLocationUseCase(private val locationRepository: LocationRepository) :
    UseCase<Location, UseCase.None>() {

    override suspend fun invoke(params: None): Location = locationRepository.getLocation()
}

LocationRepositoryImpl (уровень данных):

class LocationRepositoryImpl(private val locationDeviceDataSource: LocationDeviceDataSource) :
    LocationRepository {
    override suspend fun getLocation(): Location = locationDeviceDataSource.getLocation()
}

LocationDeviceDataSourceImpl (уровень инфраструктуры):

class LocationDeviceDataSourceImpl(private val context: Context) : LocationDeviceDataSource {

    override suspend fun getLocation(): Location =
        LocationServices.getFusedLocationProviderClient(context).lastLocation.await()
}

Как видите, в LocationDeviceDataSourceImpl мне нужен контекст, чтобы получить последнее местоположение. Я не знаю, как лучше всего предоставить контекст для источника данных. Я видел несколько примеров, но хочу понять, как лучше всего это сделать.

Я видел следующие варианты:

  • Используйте AndroidViewModel, чтобы предоставить контекст приложения для UseCase, чтобы передать его в репозиторий, чтобы, наконец, предоставить его источнику данных. Но я не уверен, что это подходящий способ, безопасен ли он и сохраняет ли он архитектурный смысл. На основе ответа Алекса

  • Другой вариант, который я видел, - это вставить androidContext через Koin в DataSource, что является еще одним способом предоставить контекст приложения. Таким образом, контексту не обязательно проходить через ViewModel, UseCase или Repository. На основе ответа Маслика

Как лучше всего интегрировать эту логику в соответствии с моей архитектурой и почему? Или это проблема в моей архитектуре?

Большое спасибо за уделенное время.


person JoeM    schedule 04.05.2020    source источник
comment
Некоторая библиотека di (/ service locator) вроде dagger или koin. Это значительно упростит код вашего приложения. Вам не нужно передавать некоторую зависимость от фрагмента до источника данных.   -  person denvercoder9    schedule 04.05.2020
comment
@sonnet Да, я сейчас использую то, что вы говорите. Я вставляю контекст в DataSource с помощью Koin. Думаю, это лучший вариант, чем AndroidViewModel. Но я хотел знать, хороший ли это вариант или есть лучший. Большое спасибо за ответ.   -  person JoeM    schedule 05.05.2020