I am developing an Android application with Kotlin in which I need to get the current location of the mobile device. I've already found a way to do it in various examples, but I don't know how to integrate this logic according to Clean Architecture with MVVM.
In my architecture I have the following layers: Presentation, UseCase, Data, Domain and Framework. I have the presentation layer organized with the MVVM pattern. Also I use Koin for dependency injection.
I get all the data that my application needs from the DataSources that are in the Framework layer. For example, data obtained remotely or from a database, or data provided by the device (location).
Here is an example of the files involved in obtaining the location from the ViewModel:
ConfigurationViewModel (Presentation layer):
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 (Usecase layer):
class GetLocationUseCase(private val locationRepository: LocationRepository) :
UseCase<Location, UseCase.None>() {
override suspend fun invoke(params: None): Location = locationRepository.getLocation()
}
LocationRepositoryImpl (Data layer):
class LocationRepositoryImpl(private val locationDeviceDataSource: LocationDeviceDataSource) :
LocationRepository {
override suspend fun getLocation(): Location = locationDeviceDataSource.getLocation()
}
LocationDeviceDataSourceImpl (Framework layer):
class LocationDeviceDataSourceImpl(private val context: Context) : LocationDeviceDataSource {
override suspend fun getLocation(): Location =
LocationServices.getFusedLocationProviderClient(context).lastLocation.await()
}
As you can see, in LocationDeviceDataSourceImpl I need the context to get the last location. I don't know what is the best way to provide the context to the DataSource. I have seen several examples but I want to understand what is the best way to do it.
I have seen the following options:
Use AndroidViewModel, to provide the context of the application to the UseCase, to provide it to the Repository to finally provide it to the DataSource. But I am not sure if it is a suitable way, if it is safe and if it maintains the sense of architecture. Based on Alex's answer
The other option that I have seen is to inject the androidContext through Koin to the DataSource, which is another way to provide the context of the application. In this way it would not be necessary for the context to go through the ViewModel, the UseCase or the Repository. Based on maslick's answer
What would be the appropriate way to integrate this logic according to my architecture and why? Or is this problem because of my architecture?
Thanks a lot for your time.