You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Compose中Google Map的MarkerInfoWindow点击后不重组问题

问题:Jetpack Compose中Google Map标记信息窗口点击后不更新内容

我在Jetpack Compose里尝试更新Google Map的MarkerInfoWindow内容,给MarkerInfoWindow加了点击事件,点击时修改地图层级定义的favorite变量,这个变量会传给Marker,根据变量值决定是否显示额外的Text。

现在的问题是,点击Marker后变量确实改了(已经用调试断点验证过),但信息窗口没变化!favorite文本不显示,就像没触发重组一样。

我的Google Map代码如下:

GoogleMap(
    modifier = Modifier.fillMaxSize(),
    cameraPositionState = cameraPositionState
) {
    val bitmapDescriptor: BitmapDescriptor by remember { mutableStateOf(BitmapDescriptorFactory.fromResource(R.drawable.place)) }

    for (busStop in uiState.data) {
        var favorite by remember { mutableStateOf(false) }

        val markerState = rememberMarkerState(position = LatLng(busStop.lat, busStop.lon))
        CustomMarker(
            favorite = favorite,
            busStop = busStop,
            markerState = markerState,
            bitmapDescriptor = bitmapDescriptor,
            showMarker = showMarkers,
            onMarkerClicked = { favorite = !favorite }
        )
    }
}

我的CustomMarker代码如下:

@Composable
fun CustomMarker(
    favorite: Boolean,
    busStop: BusStop,
    markerState: MarkerState,
    bitmapDescriptor: BitmapDescriptor,
    showMarker: Boolean,
    onMarkerClicked: () -> Unit,
    modifier: Modifier = Modifier
) {
    MarkerInfoWindowContent(
        state = markerState,
        icon = bitmapDescriptor,
        visible = (showMarker),
        onInfoWindowClick = {
            onMarkerClicked()
        }
    ) {
        Column(
            modifier = modifier.wrapContentSize().padding(8.dp),
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Text(text = busStop.id.toString(), color = Color.Red)
            Text(text = busStop.name, color = Color.Red)

            if (favorite)
                Text("favorite")
        }
    }
}

解决方案

核心原因

Google Maps Compose的MarkerInfoWindowContent是把Compose内容一次性渲染成静态Bitmap,状态变化后不会自动重新渲染信息窗口——哪怕你的favorite变量改了,它也不会感知到,自然不会更新显示内容。

修复步骤

  1. 统一管理收藏状态
    把原来每个Marker单独的favorite状态,换成全局的状态容器(比如用mutableStateMap),避免循环重组导致状态异常。比如在ViewModel或父Compose中定义:
// 假设BusStop的id是Int类型,用这个Map存每个站点的收藏状态
val favoriteBusStops = mutableStateMapOf<Int, Boolean>()
  1. 点击后强制刷新信息窗口
    在信息窗口点击事件里,除了更新状态,还要调用markerState.showInfoWindow()强制重新渲染内容。修改CustomMarker:
@Composable
fun CustomMarker(
    favorite: Boolean,
    busStop: BusStop,
    markerState: MarkerState,
    bitmapDescriptor: BitmapDescriptor,
    showMarker: Boolean,
    onMarkerClicked: () -> Unit,
    modifier: Modifier = Modifier
) {
    MarkerInfoWindowContent(
        state = markerState,
        icon = bitmapDescriptor,
        visible = showMarker,
        onInfoWindowClick = {
            onMarkerClicked()
            // 强制刷新信息窗口,触发内容重新渲染
            markerState.showInfoWindow()
        }
    ) {
        Column(
            modifier = modifier.wrapContentSize().padding(8.dp),
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Text(text = busStop.id.toString(), color = Color.Red)
            Text(text = busStop.name, color = Color.Red)

            if (favorite) {
                Text("favorite")
            }
        }
    }
}
  1. 更新父组件的状态引用
    把原来循环里的局部favorite变量,换成从全局状态Map中获取:
GoogleMap(
    modifier = Modifier.fillMaxSize(),
    cameraPositionState = cameraPositionState
) {
    val bitmapDescriptor: BitmapDescriptor by remember { mutableStateOf(BitmapDescriptorFactory.fromResource(R.drawable.place)) }
    // 引用全局的收藏状态Map
    val favoriteBusStops = viewModel.favoriteBusStops

    for (busStop in uiState.data) {
        // 从Map中获取当前站点的收藏状态,默认未收藏
        val isFavorite = favoriteBusStops.getOrDefault(busStop.id, false)
        val markerState = rememberMarkerState(position = LatLng(busStop.lat, busStop.lon))
        
        CustomMarker(
            favorite = isFavorite,
            busStop = busStop,
            markerState = markerState,
            bitmapDescriptor = bitmapDescriptor,
            showMarker = showMarkers,
            onMarkerClicked = { 
                // 更新Map中的状态
                favoriteBusStops[busStop.id] = !isFavorite 
            }
        )
    }
}

额外提示

  • 如果不想用全局状态Map,也可以保留每个Marker的局部remember状态,但必须确保在状态变化后调用markerState.showInfoWindow(),否则信息窗口还是不会更新。
  • 用mutableStateMap的好处是状态更稳定,不会因为Compose重组导致状态丢失,同时能统一管理所有站点的收藏状态。

内容的提问来源于stack exchange,提问作者NullPointerException

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 13:45:11