Jetpack Compose中Google Map避免缩放判断致重复重组的方案
解决Jetpack Compose Google Map缩放控制标记显示时的卡顿问题
问题根源
你之前的写法每次拖动相机(zoom变化)都会触发重组,当zoom>15时会重新创建所有Marker实例,大量Marker反复实例化销毁直接导致卡顿。用derivedStateOf只是包装了判断条件,但本质还是通过重组来添加/移除Marker,没解决核心问题。
解决方案:控制Marker可见性而非动态创建/移除
核心思路是一次性创建所有Marker,通过监听缩放变化来切换它们的isVisible状态,避免重复实例化:
提前缓存资源和Marker状态
把BitmapDescriptor和所有Marker的状态一次性初始化并记住,避免每次重组重复创建:val cameraPositionState = rememberCameraPositionState { position = CameraPosition.fromLatLngZoom(city, 13f) } // 缓存图标资源,避免重复加载 val bitmapDescriptor = remember { BitmapDescriptorFactory.fromResource(R.drawable.ic_bus_mini) } // 一次性创建所有Marker的状态,数据更新时才重新生成 val markerStates = remember(uiState.data) { uiState.data.map { busStop -> rememberMarkerState(position = LatLng(busStop.lat, busStop.lon)) to busStop.name } }监听缩放变化,动态切换Marker可见性
用LaunchedEffect配合snapshotFlow监听zoom变化,只更新Marker的可见性,不触发重组创建新Marker:LaunchedEffect(cameraPositionState) { // 只监听zoom的变化,减少不必要的回调 snapshotFlow { cameraPositionState.position.zoom } .collect { currentZoom -> val shouldShowMarkers = currentZoom > 15 markerStates.forEach { (markerState, _) -> markerState.isVisible = shouldShowMarkers } } }在Map中添加所有Marker
直接把所有Marker添加到Map里,不用if判断,通过isVisible控制显示:GoogleMap(modifier = Modifier.fillMaxSize(), cameraPositionState = cameraPositionState) { markerStates.forEach { (state, title) -> Marker( state = state, title = title, icon = bitmapDescriptor ) } }
为什么这个方法有效?
- 所有Marker只会在初始化或数据更新时创建一次,不会随相机拖动反复销毁重建
- 只修改Marker的
isVisible属性,这是轻量操作,不会引发大量重组 snapshotFlow精准监听zoom变化,避免无关的相机移动(比如平移)触发回调
内容的提问来源于stack exchange,提问作者NullPointerException
相关产品推荐
相关产品推荐

