I am using Google Maps in my Android app, I am displaying markers that are in visible regions on maps.
Is this the correct approach to fetch markers from the Room Database?
I could use paging to get data faster.
When the user navigates to MapScreen
, the UI kind of lags. It takes a while to display all markers and load the map
@Composable
fun MapScreen(viewModel: MapViewModel = viewModel()) {
val scope = rememberCoroutineScope()
val context = LocalContext.current
var mapProperties by remember { mutableStateOf(MapProperties(mapType = MapType.NORMAL)) }
var mapUiSettings by remember { mutableStateOf(MapUiSettings(zoomControlsEnabled = false)) }
var mapVisible by remember { mutableStateOf(false) }
val markerList by viewModel.markers.collectAsState()
GoogleMap(
modifier = Modifier.fillMaxSize(),
properties = mapProperties,
uiSettings = mapUiSettings,
onMapLoaded = {
mapVisible = true
}
) {
markerList.forEach { marker ->
Marker(
state = MarkerState(position = LatLng(marker.latitude, marker.longitude)),
title = marker.title,
snippet = marker.snippet
)
}
}
LaunchedEffect(cameraPositionState.position) {
visibleRegion.value = cameraPositionState.projection?.visibleRegion?.latLngBounds
mapViewModel.fetchMapTrains(visibleRegion.value, zoomLevel = zoomLevel, isFavorite = isFav)
}
}
// ViewModel
class MapViewModel @Inject constructor(private val repository: MapRepository) : ViewModel() {
private val _visibleRegion = MutableStateFlow<LatLngBounds?>(null)
private val visibleRegion: StateFlow<LatLngBounds?> = _visibleRegion.asStateFlow()
val markers: StateFlow<List<MarkerEntity>> = visibleRegion
.flatMapLatest { region ->
if (region == null) {
flowOf(emptyList())
} else {
repository.getMarkersInRegion(
region.southwest.latitude,
region.southwest.longitude,
region.northeast.latitude,
region.northeast.longitude
)
}
}
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), emptyList())
fun updateVisibleRegion(bounds: LatLngBounds) {
_visibleRegion.value = bounds
}
}
// Repository
class MapRepository @Inject constructor(private val markerDao: MarkerDao) {
fun getMarkersInRegion(
minLat: Double,
minLng: Double,
maxLat: Double,
maxLng: Double
): Flow<List<MarkerEntity>> {
return markerDao.getMarkersInRegion(minLat, minLng, maxLat, maxLng)
}
suspend fun insertMarker(marker: MarkerEntity) {
markerDao.insertMarker(marker)
}
}
// DAO
@Dao
interface MarkerDao {
@Query("""
SELECT * FROM markers
WHERE latitude BETWEEN :minLat AND :maxLat
AND longitude BETWEEN :minLng AND :maxLng
""")
fun getMarkersInRegion(
minLat: Double,
minLng: Double,
maxLat: Double,
maxLng: Double
): Flow<List<MarkerEntity>>
}