- 代码为github
我在做一个地震Map应用。
该应用程序从2个Web API获取地震信息,并在GoogleMap上显示位置。
在MainScreen.kt中,它通过使用forEach()获取数据列表并在Map上放置标记。
MainScreen.kt
@Composable
fun MainScreen(
viewModel: MainViewModel = hiltViewModel()
) {
val items = viewModel.uiState.collectAsStateWithLifecycle()
if (items.value is MainActivityUiState.Success) {
MainScreen((items.value as MainActivityUiState.Success).earthquakeData)
} else {
val noItemList = emptyList<EarthquakeInfo>()
MainScreen(noItemList)
}
}
@Composable
internal fun MainScreen(
items: List<EarthquakeInfo>
) {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
Column {
val tokyo = LatLng(35.6812, 139.7671)
val cameraPositionState = rememberCameraPositionState {
position = CameraPosition.fromLatLngZoom(tokyo, 0f)
}
GoogleMap(
modifier = Modifier.weight(1f),
cameraPositionState = cameraPositionState
) {
items.forEach {
Marker(
position = LatLng(it.latitude, it.longitude),
title = it.place,
snippet = it.place
)
}
}
...
}
}
}
字符串
MainViewModel.kt
@HiltViewModel
class MainViewModel @Inject constructor(
usgsEarthquakeRepository: UsgsEarthquakeRepository,
p2pquakeRepository: P2pquakeRepository,
@DefaultDispatcher defaultDispatcher: CoroutineDispatcher,
) : ViewModel() {
val uiState: StateFlow<MainActivityUiState> =
try {
GetLatestEarthquakeInfoUseCase(
usgsEarthquakeRepository,
p2pquakeRepository,
)
.invoke()
.flowOn(defaultDispatcher)
.map<List<EarthquakeInfo>, MainActivityUiState>(::Success)
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5000),
initialValue = MainActivityUiState.Loading,
)
} catch (e: IOException) {
MutableStateFlow(MainActivityUiState.Error).asStateFlow()
}
}
sealed interface MainActivityUiState {
object Loading: MainActivityUiState
data class Success(val earthquakeData: List<EarthquakeInfo>): MainActivityUiState
object Error: MainActivityUiState
}
型
在GetLatestEarthquakeInfoUseCase.kt中,它需要合并来自API的数据,但它们具有不同的数据结构,因此我使用map()创建EarthquakeInfo数据类并放入必要的数据。
然后使用合并返回数据列表。
GetLatestEarthquakeInfoUseCase.kt
class GetLatestEarthquakeInfoUseCase @Inject constructor(
private val usgsEarthquakeRepository: UsgsEarthquakeRepository,
private val p2pquakeRepository: P2pquakeRepository,
) {
operator fun invoke(): Flow<List<EarthquakeInfo>> {
val usgsEarthquakeFlow =
usgsEarthquakeRepository
.getInfo("geojson", 20, "time")
.map { usgsEarthquakeInfo ->
usgsEarthquakeInfo.features
.map { feature ->
EarthquakeInfo(
feature.properties.getDatetime(),
feature.properties.place ?: "",
feature.geometry.coordinates[1],
feature.geometry.coordinates[0],
feature.properties.mag,
feature.geometry.getDepth(),
)
}
}
val p2pEarthquakeFlow =
p2pquakeRepository
.getInfo(10, 0)
.map { p2pquakeInfo ->
p2pquakeInfo.map { data ->
EarthquakeInfo(
data.earthquake.getDatetime(),
data.earthquake.hypocenter.name,
data.earthquake.hypocenter.latitude,
data.earthquake.hypocenter.longitude,
data.earthquake.hypocenter.magnitude,
data.earthquake.hypocenter.depth,
)
}
}
return merge(usgsEarthquakeFlow, p2pEarthquakeFlow)
}
}
型
当我运行代码时,它显示来自p2pEarthquakeFlow的标记,持续1秒,然后消失,然后显示来自usgsEarthquakeFlow的标记。
我想显示这两个,但它最终只显示usgsEarthquakeFlow数据。
你能帮帮我吗?
我是AndroidKotlin的新手,英语是我的第二语言,所以如果我犯了错误,请让我知道。
我会解决的
1条答案
按热度按时间3zwjbxry1#
正如本文所述,merge()不会等待另一个流。
当我把
字符串
下
型
在MainScreen.kt中,它交替显示来自P2P和USGS的数据。
这会导致MainScreen.kt中的Marker()重新组合,首先显示P2P数据并删除它们,然后显示USGS数据。
我将存储库改为返回List<>,并在用例中改为从List<>创建EarthquakeInfo数据,然后发出(List<> + List<>)