[go: nahoru, domu]

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using rememberCameraPositionState and observing it via a lambda, makes entire map recompose instead of just of the lambda #216

Open
ForceGT opened this issue Oct 31, 2022 · 7 comments
Labels
priority: p3 Desirable enhancement or fix. May not be included in next release. type: question Request for information or clarification. Not an issue.

Comments

@ForceGT
Copy link
ForceGT commented Oct 31, 2022

I am using the rememberCameraPositionState like so, and then exposing a callback from my custom google map wrapper to observe the state

val cameraPositionState = 
        rememberCameraPositionState {
            position =
                CameraPosition.fromLatLngZoom(
                    mapInitialTargetLocation,
                    14f
                )
    
//Custom callback exposed from map            
 onMapCameraPositionStateChanged: (CameraPositionState) -> Unit = {},
        

However when I try to use this map, and trigger an operation from the viewModel, it recomposes infinitely

fun ParentComposable(){

 MapContent(viewModel::onCameraPositionStateChanged)

}

//Calling this function from above parent composable like so
// CustomerMap is my own wrapper around GoogleMap for convenience

private fun MapContent(
    onCameraStateChanged : (CameraPositionState) -> Unit
) {
        CustomerMap(
            ......,
            
         }

What am I doing wrong, or is it just a Google Map issue?

@arriolac
Copy link
Member

That behavior is expected—this is why you can't set a camera change listener on the GoogleMap composable function. cameraPositionState.position changes as the camera is changed so you can observe based on that.

@arriolac arriolac added the type: question Request for information or clarification. Not an issue. label Oct 31, 2022
@ForceGT
Copy link
Author
ForceGT commented Nov 1, 2022

I could find out that the culprit was another unstable parameter in my composable wrapper around GoogleMap
But as I said, I was observing CameraPositionState, and expected behaviour was only the lambda which returns the state should change, and not the entire GoogleMap

@ForceGT ForceGT changed the title Using rememberCameraPositionState and observing it, makes map recompose indefinitely Using rememberCameraPositionState and observing it via a lambda, makes entire map recompose instead of just of the lambda Nov 1, 2022
@ForceGT
Copy link
Author
ForceGT commented Nov 1, 2022

@arriolac Thanks for your answer, but exposing CameraPositionState is important for my business logic, since we are observing many more values, rather than just the position. What would you recommend mend in that case?

@arriolac
Copy link
Member
arriolac commented Nov 1, 2022

I would have to see more of your implementation here like how is onMapCameraPositionStateChanged implemented? Also, what is the event handling code doing?

@ForceGT
Copy link
Author
ForceGT commented Nov 12, 2022

I finally removed the callback, and exposed a wrapper around the CameraPositionState, like so, where CustomerMap is a custom wrapper around GoogleMap

CustomerMap(
   ....
    myCameraPositionState: MutableState<MyCameraPositionState> = rememberMyCameraPositionState(),
)

where my rememberMyCameraPositionState is something like this

Composable
fun rememberMyCameraPositionState(
    key: String? = null,
    init: (() -> MyCameraPositionState)? = null
): MutableState<MyCameraPositionState> {
    return rememberSaveable(key, saver = MyCameraPositionState.Saver) {
        mutableStateOf(init?.invoke() ?: MyCameraPositionState.NONE)
    }
}

And then in my CustomerMap composable, I use a LaunchedEffect to update this

 val cameraPositionState =
        rememberCameraPositionState( )

    LaunchedEffect(cameraPositionState.position to cameraPositionState.isMoving) {
        myCameraPositionState.value = cameraPositionState.mapToMyCameraPositionState
    }

The main idea is that any dependency related to maps or maps-compose should not be needed outside this current module (where the map resides) to keep the dependencies clean

However I still feel, taking a MutableState as a method parameter, is not correct, what do you think?

@aleksisjoberg
Copy link
aleksisjoberg commented Dec 23, 2022

I think I have the same issue. This is especially a problem with TileOverlay, as it gets needlessly recomposed (=tiles removed & added) every time as the parent composable (GoogleMap) recomposes. Is there any way to prevent that, while still being able to observe changes to camera's position, which is needed to load more markers?

EDIT: Passing the TileOverlay as a parameter from the parent composable fixed my issue. At this point I don't really understand what's going on and why it works, but keeping the TileOverlay hierarchically "above" the component that manages map's state was the fix for me.

@stale
Copy link
stale bot commented Jun 18, 2023

This issue has been automatically marked as stale because it has not had recent activity. Please comment here if it is still valid so that we can reprioritize. Thank you!

@stale stale bot added the stale label Jun 18, 2023
@kikoso kikoso added the priority: p3 Desirable enhancement or fix. May not be included in next release. label Jul 10, 2023
@stale stale bot removed the stale label Jul 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
priority: p3 Desirable enhancement or fix. May not be included in next release. type: question Request for information or clarification. Not an issue.
Projects
None yet
Development

No branches or pull requests

4 participants