You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Compose中使用MapBox调用flyTo()触发MapInitOptions修改异常求助

MapBox Jetpack Compose:flyTo触发Mutating MapInitOptions异常的解决方法

问题场景

在Jetpack Compose中使用MapBox,调用mapViewportState.flyTo()设置地图目标位置时,抛出Mutating MapInitOptions during composition is not allowed异常。移除mapInitOptionsFactory = { MapInitOptions(...) }配置后功能正常,但会丢失自定义地图样式。

原代码:

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 = { // 注释掉这段就正常
            MapInitOptions(
                context = context,
                styleUri = Style.DARK,
            )
        }
    )
}

错误日志

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)

解决方法

将MapInitOptions的创建用remember包裹,确保重组时复用同一个实例,避免触发MapBox的检查逻辑:

val mapViewportState = rememberMapViewportState()
LaunchedEffect(key1 = userInitialLocation) {
    userInitialLocation?.let { userLocation ->
        mapViewportState.flyTo(
            cameraOptions = mapViewportState.cameraState.toCameraOptions()
                .center(
                    Point.fromLngLat(
                        userLocation.longitude,
                        userLocation.latitude
                    )
                )
                .zoom(16.0)
                .build()
        )
    }
}
val context = LocalContext.current
// 用remember缓存MapInitOptions实例
val mapInitOptions = remember {
    MapInitOptions(
        context = context,
        styleUri = Style.DARK,
    )
}
if (isLocationPermissionGranted) {
    MapboxMap(
        modifier = Modifier.fillMaxSize(),
        mapViewportState = mapViewportState,
        mapInitOptionsFactory = { mapInitOptions }
    )
}

原因说明

MapBox的Compose组件不允许在重组过程中修改或替换MapInitOptions实例。原代码中每次重组都会通过mapInitOptionsFactory创建新的MapInitOptions,触发了内部的非法状态检查。用remember包裹后,实例仅在首次组合时创建,后续重组复用同一实例,符合MapBox的约束要求。

内容的提问来源于stack exchange,提问作者user924

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 22:51:07