From bb1a277e435105035943f0ebc41e864c534a5b18 Mon Sep 17 00:00:00 2001 From: Uli Bubenheimer Date: Mon, 29 Jan 2024 03:55:41 -0500 Subject: [PATCH] fix!: leverage `@StateFactoryMarker` to flag State object creation without remember or similar mechanisms. The PR replaces public constructors on State objects with `invoke()` factory functions in public companion objects. `@StateFactoryMarker` can only be applied to functions, not constructors. The chosen constructor replacement approach minimizes the required refactoring impact on correct State object usages, requiring no refactoring in the vast majority of cases. Fixes #506 --- .../maps/android/compose/CameraPositionState.kt | 13 ++++++++++++- .../com/google/maps/android/compose/Marker.kt | 15 ++++++++++++--- .../google/maps/android/compose/TileOverlay.kt | 10 +++++++++- .../streetview/StreetViewCameraPositionState.kt | 12 +++++++++++- 4 files changed, 44 insertions(+), 6 deletions(-) diff --git a/maps-compose/src/main/java/com/google/maps/android/compose/CameraPositionState.kt b/maps-compose/src/main/java/com/google/maps/android/compose/CameraPositionState.kt index 776833d2..98f07ada 100644 --- a/maps-compose/src/main/java/com/google/maps/android/compose/CameraPositionState.kt +++ b/maps-compose/src/main/java/com/google/maps/android/compose/CameraPositionState.kt @@ -22,6 +22,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.saveable.Saver import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue +import androidx.compose.runtime.snapshots.StateFactoryMarker import androidx.compose.runtime.staticCompositionLocalOf import com.google.android.gms.maps.CameraUpdate import com.google.android.gms.maps.CameraUpdateFactory @@ -59,7 +60,7 @@ public inline fun rememberCameraPositionState( * * @param position the initial camera position */ -public class CameraPositionState( +public class CameraPositionState private constructor( position: CameraPosition = CameraPosition(LatLng(0.0, 0.0), 0f, 0f, 0f) ) { /** @@ -302,6 +303,16 @@ public class CameraPositionState( } public companion object { + /** + * Creates a new [CameraPositionState] object + * + * @param position the initial camera position + */ + @StateFactoryMarker + public operator fun invoke( + position: CameraPosition = CameraPosition(LatLng(0.0, 0.0), 0f, 0f, 0f) + ): CameraPositionState = CameraPositionState(position) + /** * The default saver implementation for [CameraPositionState] */ diff --git a/maps-compose/src/main/java/com/google/maps/android/compose/Marker.kt b/maps-compose/src/main/java/com/google/maps/android/compose/Marker.kt index 1904abc6..92b41831 100644 --- a/maps-compose/src/main/java/com/google/maps/android/compose/Marker.kt +++ b/maps-compose/src/main/java/com/google/maps/android/compose/Marker.kt @@ -27,6 +27,7 @@ import androidx.compose.runtime.rememberCompositionContext import androidx.compose.runtime.saveable.Saver import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue +import androidx.compose.runtime.snapshots.StateFactoryMarker import androidx.compose.ui.geometry.Offset import com.google.android.gms.maps.model.AdvancedMarkerOptions import com.google.android.gms.maps.model.BitmapDescriptor @@ -72,9 +73,7 @@ public enum class DragState { * * @param position the initial marker position */ -public class MarkerState( - position: LatLng = LatLng(0.0, 0.0), -) { +public class MarkerState private constructor(position: LatLng) { /** * Current position of the marker. */ @@ -113,6 +112,16 @@ public class MarkerState( } public companion object { + /** + * Creates a new [MarkerState] object + * + * @param position the initial marker position + */ + @StateFactoryMarker + public operator fun invoke( + position: LatLng = LatLng(0.0, 0.0) + ): MarkerState = MarkerState(position) + /** * The default saver implementation for [MarkerState] */ diff --git a/maps-compose/src/main/java/com/google/maps/android/compose/TileOverlay.kt b/maps-compose/src/main/java/com/google/maps/android/compose/TileOverlay.kt index 18679b9b..6c78a80e 100644 --- a/maps-compose/src/main/java/com/google/maps/android/compose/TileOverlay.kt +++ b/maps-compose/src/main/java/com/google/maps/android/compose/TileOverlay.kt @@ -21,6 +21,7 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue +import androidx.compose.runtime.snapshots.StateFactoryMarker import com.google.android.gms.maps.model.TileOverlay import com.google.android.gms.maps.model.TileProvider import com.google.maps.android.ktx.addTileOverlay @@ -122,7 +123,7 @@ public fun TileOverlay( * * [clearTileCache] can be called to request that the map refresh these tiles. */ -public class TileOverlayState { +public class TileOverlayState private constructor() { internal var tileOverlay: TileOverlay? by mutableStateOf(null) @@ -139,6 +140,13 @@ public class TileOverlayState { .clearTileCache() } + public companion object { + /** + * Creates a new [TileOverlayState] object + */ + @StateFactoryMarker + public operator fun invoke(): TileOverlayState = TileOverlayState() + } } @Composable diff --git a/maps-compose/src/main/java/com/google/maps/android/compose/streetview/StreetViewCameraPositionState.kt b/maps-compose/src/main/java/com/google/maps/android/compose/streetview/StreetViewCameraPositionState.kt index 2c5c16b7..2d5a4d40 100644 --- a/maps-compose/src/main/java/com/google/maps/android/compose/streetview/StreetViewCameraPositionState.kt +++ b/maps-compose/src/main/java/com/google/maps/android/compose/streetview/StreetViewCameraPositionState.kt @@ -5,6 +5,7 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue +import androidx.compose.runtime.snapshots.StateFactoryMarker import com.google.android.gms.maps.StreetViewPanorama import com.google.android.gms.maps.model.LatLng import com.google.android.gms.maps.model.StreetViewPanoramaCamera @@ -18,7 +19,7 @@ public inline fun rememberStreetViewCameraPositionState( StreetViewCameraPositionState().apply(init) } -public class StreetViewCameraPositionState { +public class StreetViewCameraPositionState private constructor() { /** * The location of the panorama. @@ -86,4 +87,13 @@ public class StreetViewCameraPositionState { public fun setPosition(panoId: String) { panorama?.setPosition(panoId) } + + public companion object { + /** + * Creates a new [StreetViewCameraPositionState] object + */ + @StateFactoryMarker + public operator fun invoke(): StreetViewCameraPositionState = + StreetViewCameraPositionState() + } } \ No newline at end of file