Skip to content

Setting CameraPositionState.position is not stateful #523

Description

@bubenheimer

android-maps-compose 4.3.3

Setting CameraPositionState.position is not stateful. (Setting the property calls through to the GoogleMap SDK and immediately changes the camera position on the map.) This is an invalid Compose architectural decision:

  1. Reading this property is stateful: it reads from a state.
  2. The class has State in its name, and position is its primary public property, so setting it must be stateful to not completely defy user expectations.
  3. Not even the KDoc mentions setting not being stateful.
  4. By contrast, setting MarkerState.position is stateful. The behavior of CameraPositionState is different when it should be the same.

The general impact is that setting it via snapshot state does not work correctly. This is a fundamental violation of normal Compose behavior.

For example, a user might attempt something like this to control camera position, which mimics the behavior of rememberUpdatedState(), but for CameraPositionState instead of MutableState:

@Composable
fun MapWithCamera(cameraPosition: CameraPosition) {
    val cameraState = rememberCameraPositionState(position = cameraPosition)
        .also { it.position = cameraPosition }

    GoogleMap(
        cameraPositionState = cameraState
    )
}

This approach is normally sound, but not valid here, because setting CameraStatePosition.position is a side effect (irreversible), instead of setting snapshot state. For example, if the composition is cancelled, the new camera position remains set.

CameraPositionState.move() can only be called from the main thread, so disallowing setter access in favor of this method is not a great workaround.

/**
* Current position of the camera on the map.
*/
public var position: CameraPosition
get() = rawPosition
set(value) {
synchronized(lock) {
val map = map
if (map == null) {
rawPosition = value
} else {
map.moveCamera(CameraUpdateFactory.newCameraPosition(value))
}
}
}

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    priority: p1Important issue which blocks shipping the next release. Will be fixed prior to next release.type: bugError or flaw in code with unintended results or allowing sub-optimal usage patterns.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions