I have a singleton LocationRepository class and inside that I have a callbackFlow method which gets location updates from FusedLocationProvider. And a Service class that collects that flow. The thing is I want to use that location info in an Activity too.
class LocationRepositoryImpl @Inject constructor(
private val api: Api,
private val fusedClient: FusedLocationProviderClient,
@ApplicationContext private val context: Context
) : LocationRepository {
private val _lastLocation = MutableStateFlow<Location?>(null)
val lastLocation = _lastLocation.asStateFlow()
override fun getLocationUpdates(hasLocationPermissions: Boolean): Flow<Location> =
callbackFlow {
val locationRequestTimeInterval =
ConfigManager.getInstance().locationRequestFromDeviceTimeLimitMs
val locationManager =
context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
val isGpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
val isNetworkEnabled =
locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
if (!isGpsEnabled && !isNetworkEnabled) {
throw LocationRepository.LocationException()
}
val locationCallback: LocationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
locationResult.lastLocation?.let { location ->
lastFuseLocationTime = System.currentTimeMillis()
_lastLocation.update { location }
trySend(location)
}
}
}
val locationRequest = LocationRequest.Builder(locationRequestTimeInterval)
.setMinUpdateIntervalMillis(locationRequestTimeInterval)
.setWaitForAccurateLocation(false)
.setPriority(Priority.PRIORITY_HIGH_ACCURACY)
.build()
if (hasLocationPermissions) {
fusedClient.requestLocationUpdates(
locationRequest,
locationCallback,
Looper.getMainLooper()
)
}
awaitClose {
fusedClient.removeLocationUpdates(locationCallback)
}
}
}
There are several ways I have in mind to achieve that,
- Using something like an event bus (LocalBroadcastManager maybe) to send Location info from Service to the Activity.
- Collecting that callbackFlow both in the Activity's viewModel and in the Service class.
- Defining a StateFlow in LocationRepository that holds the location info, update it when the location callback is triggered and collect it in Activity's videModel. Also collect the callBackFlow directly in the Service.
I don't want to use the first 2 because I am not sure about collecting a cold flow from multiple places and the LocalBroadcastManager is deprecated.
Is keeping aStateFlow inside a singleton repository a violation of clean architecture and MVVM?