kotlin 如何在GoogleMap上显示流量数据

y0u0uwnf  于 2023-08-06  发布在  Kotlin
关注(0)|答案(1)|浏览(138)

我在做一个地震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的新手,英语是我的第二语言,所以如果我犯了错误,请让我知道。
我会解决的

3zwjbxry

3zwjbxry1#

正如本文所述,merge()不会等待另一个流。
当我把

println(items.value)

字符串

val items = viewModel.uiState.collectAsStateWithLifecycle()


在MainScreen.kt中,它交替显示来自P2P和USGS的数据。
这会导致MainScreen.kt中的Marker()重新组合,首先显示P2P数据并删除它们,然后显示USGS数据。
我将存储库改为返回List<>,并在用例中改为从List<>创建EarthquakeInfo数据,然后发出(List<> + List<>)

相关问题