在下面我有
Box()
可组合。其中,我有 GoogleMap()
和 BottomActionBar()
自定义可组合项。问题是,当添加标记或处于拖动状态时,会导致 BottomActionBar()
组合包在标记被拖动的同时重新组合。期望的结果是,仅当 isMarkerInDragState 实际更改时,BottomActionBar()
才会重新组合,但即使标记处于相同状态并被拖动,它也会重新组合。另外,为什么 MainMapView()
会被重构,因为 Google 地图的范围仅限于 Box 可组合项。
非常感谢您的帮助!
@Composable
private fun MainMapView(
modifier: Modifier = Modifier,
lastKnownLocation: Location?,
onMapClick: (LatLng) -> Unit,
geoPoints: List<LatLng>,
isMarkerInDragState: Boolean,
onDragUpdate: (Boolean) -> Unit,
onClearMapButtonClick: () -> Unit,
onGeoPointUpdate: (MutableList<LatLng>) -> Unit
) {
Box(
modifier = modifier
.fillMaxSize()
.padding(contentPadding),
) {
val cameraPositionState = rememberCameraPositionState()
val context = LocalContext.current
val markers = mutableListOf<Unit>()
LaunchedEffect(lastKnownLocation) {
lastKnownLocation?.let {
cameraPositionState.animate(
update = CameraUpdateFactory.newLatLngZoom(
LatLng(it.latitude, it.longitude),
18f
)
)
}
}
GoogleMap(
modifier = Modifier.fillMaxSize(),
cameraPositionState = cameraPositionState,
properties = MapProperties(
isMyLocationEnabled = true,
mapType = MapType.Hybrid
),
uiSettings = MapUiSettings(
mapToolbarEnabled = false,
zoomControlsEnabled = false
),
onMapClick = {
onMapClick(it)
}
) {
if (geoPoints.isNotEmpty()) {
DrawPolygon(points = geoPoints)
for ((index, point) in geoPoints.withIndex()) {
val markerState =
rememberMarkerState(position = LatLng(point.latitude, point.longitude))
LaunchedEffect(markerState.position) {
val positions = geoPoints.toMutableList()
val pointIndex = positions.indexOf(point)
if (pointIndex < 0) {
return@LaunchedEffect
}
positions[pointIndex] = markerState.position
onGeoPointUpdate(positions)
}
LaunchedEffect(markerState.dragState) {
when (markerState.dragState) {
DragState.DRAG -> onDragUpdate(true)
DragState.START -> {}
DragState.END -> onDragUpdate(false)
}
}
val marker = Marker(
state = markerState,
visible = true,
title = "Point ${index + 1}",
draggable = true
)
markers.add(marker)
}
}
}
BottomActions(
modifier = Modifier
.align(Alignment.BottomCenter),
isVisible = geoPoints.size > 2,
onClearMapButtonClick = {
onClearMapButtonClick()
}
)
}
}
在 Jetpack Compose 中,当可组合函数读取的状态发生变化时,会发生重组,导致函数再次执行以反映更新后的状态。
在您的场景中,每次在
BottomActionBar()
上拖动标记时,都会重新组合 GoogleMap()
可组合项。这可能是因为拖动状态更改会触发 BottomActionBar()
或 MainMapView()
可组合项直接或间接观察到的状态更改。
为了防止不必要的重组,您可以使用 Jetpack Compose 的
derivedStateOf
或 snapshotFlow
来更精确地控制状态更改何时触发重组。
您可以尝试
去抖动或过滤这些更新以仅将有意义的更改传播到父可组合项,而不是在标记拖动状态更改时直接在
LaunchedEffect
内触发状态更改。
对于像
BottomActionBar()
这样只应在特定条件发生变化时重新组合的 UI 元素(例如 isMarkerInDragState
),请考虑将这些条件包装在 derivedStateOf
块中。这确保了可组合项仅在派生状态实际发生变化时才进行重组,而不仅仅是在任何观察到的状态发生变化时进行重组。
确保根据标记状态触发更新的
LaunchedEffect
块已正确键入,以防止不必要的重组。例如,键入特定的标记拖动状态或地理点更新可以限制对相关更改的重组。
@Composable
private fun MainMapView(
// Existing parameters
) {
// Your existing setup
Box {
// GoogleMap and other components
// Use derivedStateOf to control recomposition
val shouldShowBottomActions = remember { derivedStateOf { geoPoints.size > 2 && isMarkerInDragState } }
// Only recompose when shouldShowBottomActions actually changes.
if (shouldShowBottomActions.value) {
BottomActions(
// BottomActions setup
)
}
}
}
由于详细的实现将取决于您的确切需求(例如,您想要更新标记拖动状态的频率或构成“有意义的”更改的内容),因此首先要关注最小化触发重组的状态更改的范围。这涉及使用 Compose 的状态管理工具(
remember
、derivedStateOf
、snapshotFlow
)来微调可组合项被要求重组的时间和原因。