最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

android - How to avoid unnecesary recompositions due to checking a state variable? - Stack Overflow

programmeradmin1浏览0评论

I'm adding a lot of markers on a Google Map in Jetpack Compose, and it works, but I need to paint them only when zoom level is above 15, so I added if (cameraPositionState.position.zoom > 15) before adding the markers. It works also, but it works very laggy because each time I move the camera position with the finger, the map recomposes everything and adds again all the markers.

How can I avoid that recomposition each time the camera is moved?

If I remove that if if (cameraPositionState.position.zoom > 15) then the recompositions dissapear and the map is smooth again, but I need that check to avoid painting the makers if zoom level is above 15.

How to solve this?

val cameraPositionState = rememberCameraPositionState {
    position = CameraPosition.fromLatLngZoom(city, 13f)
}

GoogleMap(modifier = Modifier.fillMaxSize(), cameraPositionState = cameraPositionState) {
    if (cameraPositionState.position.zoom > 15) { // THIS LINE IS THE ISSUE
        val bitmapDescriptor = BitmapDescriptorFactory.fromResource(R.drawable.ic_bus_mini)
        for (busStop in uiState.data) {
            Marker(
                state = rememberMarkerState(position = LatLng(busStop.lat, busStop.lon)),
                title = busStop.name, icon = bitmapDescriptor,
            )
        }
    }
}

I tried a solution using derivedstateof:

val showMarkers by remember(cameraPositionState.position.zoom) {
    derivedStateOf {
        cameraPositionState.position.zoom > 15
    }
}

and changing the if by if (showMarkers) { but the issue persist, moving the camera, makes everything to recompose adding all the markers again and lagging the map.

I'm adding a lot of markers on a Google Map in Jetpack Compose, and it works, but I need to paint them only when zoom level is above 15, so I added if (cameraPositionState.position.zoom > 15) before adding the markers. It works also, but it works very laggy because each time I move the camera position with the finger, the map recomposes everything and adds again all the markers.

How can I avoid that recomposition each time the camera is moved?

If I remove that if if (cameraPositionState.position.zoom > 15) then the recompositions dissapear and the map is smooth again, but I need that check to avoid painting the makers if zoom level is above 15.

How to solve this?

val cameraPositionState = rememberCameraPositionState {
    position = CameraPosition.fromLatLngZoom(city, 13f)
}

GoogleMap(modifier = Modifier.fillMaxSize(), cameraPositionState = cameraPositionState) {
    if (cameraPositionState.position.zoom > 15) { // THIS LINE IS THE ISSUE
        val bitmapDescriptor = BitmapDescriptorFactory.fromResource(R.drawable.ic_bus_mini)
        for (busStop in uiState.data) {
            Marker(
                state = rememberMarkerState(position = LatLng(busStop.lat, busStop.lon)),
                title = busStop.name, icon = bitmapDescriptor,
            )
        }
    }
}

I tried a solution using derivedstateof:

val showMarkers by remember(cameraPositionState.position.zoom) {
    derivedStateOf {
        cameraPositionState.position.zoom > 15
    }
}

and changing the if by if (showMarkers) { but the issue persist, moving the camera, makes everything to recompose adding all the markers again and lagging the map.

Share Improve this question edited 2 days ago halfer 20.4k19 gold badges108 silver badges201 bronze badges asked Feb 7 at 8:21 NullPointerExceptionNullPointerException 37.6k80 gold badges230 silver badges402 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 4

To prevent composition on each frame when a State value change you can use derivedStateOf or SnapshotFlow.

val zoomed: Boolean by remember { derivedStateOf { cameraPositionState.position.zoom > 15 } }

But as implied in documents derivedState computation is heavy but doesn't have impact as excessive recompositions.

Other options is to use snapshotFlow inside LaunchedEffect to turn it into Flow and using a MutableState and setting its value in collect/launchIn to get a State with only 2 outcomes.

发布评论

评论列表(0)

  1. 暂无评论