在我的 Android 应用程序中,我从 Room 获取数据并将其显示在地图上。我遇到了这两种视图模型方法来获取数据。
哪一种是更有效、更好的方法?
目前我正在使用第二种方式获取数据。效果很好。只是想知道这两者之间有什么区别。
第一种方法-
private val _visibleRegion = MutableStateFlow(defaultVisibleRegion)
private val _zoomLevel = MutableStateFlow(6f)
private val _isFavorite = MutableStateFlow(false)
val mapData: StateFlow<PagingData<MapData>> = combine(
_visibleRegion,
_zoomLevel,
_isFavorite
) { region, zoom, isFav ->
Triple(region, zoom, isFav)
}.flatMapLatest { (region, zoom, isFav) ->
repo.getDataInBoundsPaged(
region.southwest.latitude,
region.northeast.latitude,
region.southwest.longitude,
region.northeast.longitude,
zoom = zoom,
isFav = isFav
)
}.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5000),
initialValue = PagingData.empty()
)
fun updateVisibleRegion(region: LatLngBounds) {
_visibleRegion.value = region
}
fun updateZoomLevel(zoom: Float) {
_zoomLevel.value = zoom
}
fun toggleFavorite(isFavorite: Boolean) {
_isFavorite.value = isFavorite
}
vs 第二种方法-
private val _mapData = MutableStateFlow<PagingData<MapData>>(PagingData.empty())
val mapData: StateFlow<PagingData<MapData>> = _mapData.asStateFlow()
private val defaultVisibleRegion = LatLngBounds(
LatLng(6.792525080049721, 70.06730787456036),
LatLng(37.411989227903604, 86.94231156259775)
)
init {
fetchMapData()
}
fun fetchMapData(
visibleRegion: LatLngBounds = defaultVisibleRegion,
zoomLevel: Float = 6f,
isFavorite: Boolean = false
) {
viewModelScope.launch {
repo.getDataInBoundsPaged(
visibleRegion.southwest.latitude,
visibleRegion.northeast.latitude,
visibleRegion.southwest.longitude,
visibleRegion.northeast.longitude,
zoom = zoomLevel,
isFav = isFavorite
)
.cachedIn(viewModelScope)
.collect {
_mapData.value = it
}
}
}
您应该避免在视图模型中收集流。如果您仅在 UI 中收集,则 UI 可以根据需要订阅和取消订阅 StateFlow,以便可以在不需要时停止底层流。当您使用
collectAsStateWithLifecycle
收集时,此操作会自动完成。
因此你不应该使用第二种方法。
第一种方法看起来不错,您可能只是想像在第二种方法中那样缓存分页数据。 Triple 转换也可以稍微简化一下:
val mapData: StateFlow<PagingData<MapData>> =
combine(
_visibleRegion,
_zoomLevel,
_isFavorite,
::Triple,
)
.flatMapLatest { (region, zoom, isFav) ->
repo.getDataInBoundsPaged(
region.southwest.latitude,
region.northeast.latitude,
region.southwest.longitude,
region.northeast.longitude,
zoom = zoom,
isFav = isFav,
)
}
.cachedIn(viewModelScope)
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5_000),
initialValue = PagingData.empty(),
)