MapBox Compose Extension: Mutating MapInitOptions during composition is not allowed exception

168 Views Asked by At

I'm trying to use MapBox in Compose and set the needed location on the map using mapViewportState.flyTo() function but it fails with the mentioned exception for some reason, and it's related to using mapInitOptionsFactory = { MapInitOptions(...) }, if I remove mapInitOptionsFactory line code then it works, but it means of course I get default map style

val mapViewportState = rememberMapViewportState
LaunchedEffect(key1 = userInitialLocation) {
    userInitialLocation?.let { userLocation ->
        mapViewportState.flyTo(
            cameraOptions = mapViewportState.cameraState.toCamera
                .center(
                    Point.fromLngLat(
                        userLocation.longitude,
                       userLocation.latitude
                    )
                )
                .zoom(16.0)
                .build()
        )
    }
}
val context = LocalContext.current
if (isLocationPermissionGranted) {
    MapboxMap(
        modifier = Modifier.fillMaxSize(),
        mapViewportState = mapViewportState,
         mapInitOptionsFactory = { // if I comment out this part then it works fine
             MapInitOptions(
                 context = context,
                 styleUri = Style.DARK,
             )
         }
    )

Logcat:

Error was captured in composition while live edit was enabled.
                 java.lang.IllegalStateException: Mutating MapInitOptions during composition is not allowed.
                    at com.mapbox.maps.extension.compose.internal.MapboxMapNodeKt$MapboxMapComposeNode$2$1.invoke(MapboxMapNode.kt:136)
                    at com.mapbox.maps.extension.compose.internal.MapboxMapNodeKt$MapboxMapComposeNode$2$1.invoke(MapboxMapNode.kt:135)
                    at androidx.compose.runtime.ComposerImpl$apply$operation$1.invoke(Composer.kt:1712)
                    at androidx.compose.runtime.ComposerImpl$apply$operation$1.invoke(Composer.kt:1710)
                    at androidx.compose.runtime.CompositionImpl.applyChangesInLocked(Composition.kt:818)
                    at androidx.compose.runtime.CompositionImpl.applyChanges(Composition.kt:849)
                    at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$1.invoke(Recomposer.kt:625)
                    at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$1.invoke(Recomposer.kt:537)
                    at androidx.compose.ui.platform.AndroidUiFrameClock$withFrameNanos$2$callback$1.doFrame(AndroidUiFrameClock.android.kt:41)
                    at androidx.compose.ui.platform.AndroidUiDispatcher.performFrameDispatch(AndroidUiDispatcher.android.kt:109)
                    at androidx.compose.ui.platform.AndroidUiDispatcher.access$performFrameDispatch(AndroidUiDispatcher.android.kt:41)
                    at androidx.compose.ui.platform.AndroidUiDispatcher$dispatchCallback$1.doFrame(AndroidUiDispatcher.android.kt:69)
                    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1229)
                    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1239)
                    at android.view.Choreographer.doCallbacks(Choreographer.java:899)
                    at android.view.Choreographer.doFrame(Choreographer.java:827)
                    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1214)
                    at android.os.Handler.handleCallback(Handler.java:942)
                    at android.os.Handler.dispatchMessage(Handler.java:99)
                    at android.os.Looper.loopOnce(Looper.java:201)
                    at android.os.Looper.loop(Looper.java:288)
                    at android.app.ActivityThread.main(ActivityThread.java:7872)
                    at java.lang.reflect.Method.invoke(Native Method)
                    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
                    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
1

There are 1 best solutions below

0
Dark White On

mapInitOptionsFactory has it own context

mapInitOptionsFactory = { context -> // use this context }

In your example:

// val context = LocalContext.current // Remove this
    MapboxMap(
            modifier = Modifier.fillMaxSize(),
            mapViewportState = mapViewportState,
            mapInitOptionsFactory = {context->
                MapInitOptions(
                    context = context,
                    styleUri = Style.DARK,
            )
        }
    )

Source: Mapbox github - Setup the Map Style and set the initial camera position