为什么谷歌地图会导致其他可组合项的重组?

问题描述 投票:0回答:1

在下面我有

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()
            }
        )
    }
}
google-maps android-jetpack-compose android-jetpack jetpack
1个回答
0
投票

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
)来微调可组合项被要求重组的时间和原因。

© www.soinside.com 2019 - 2024. All rights reserved.