Flutter应用开启myLocationEnabled时点击返回键崩溃问题求助
Flutter Mapbox 返回键崩溃问题(myLocationEnabled=true时)
你的崩溃核心问题是WillPopScope里的执行顺序错误:你先调用了Navigator.pop(context),这会立即将当前页面从导航栈中移除,页面组件开始销毁,后续的setState根本不会被执行——因为页面已经不存在了。这就导致Mapbox组件在销毁时,myLocationEnabled仍为true,原生层的定位相关资源释放时出现空指针(对应报错里的SEGV_MAPERR,即访问了空内存地址)。
修复步骤
- 调整返回逻辑的执行顺序:先更新
location状态禁用定位,等待状态更新完成后再执行页面弹出操作。 - 在页面销毁时手动清理定位资源:重写
dispose方法,确保Mapbox的定位功能在组件销毁前被关闭,避免原生层资源泄漏。
修改后的代码示例
bool location = true; MapboxMapController? controller; @override Widget build(BuildContext context) { return WillPopScope( onWillPop: () async { // 先禁用定位,触发组件更新 setState(() { location = false; }); // 等待一帧确保状态更新完成,再弹出页面 await Future.delayed(const Duration(milliseconds: 100)); Navigator.pop(context); return true; }, child: Scaffold( appBar: AppBar(title: const Text('Restaurants Map')), body: SafeArea( child: Stack( children: [ SizedBox( height: MediaQuery.of(context).size.height * 1, child: MapboxMap( accessToken: dotenv.env['MAPBOX_ACCESS_TOKEN'], initialCameraPosition: _initialCameraPosition, onMapCreated: _onMapCreated, onStyleLoadedCallback: _onStyleLoadedCallback, myLocationEnabled: location, myLocationTrackingMode: MyLocationTrackingMode.TrackingGPS, minMaxZoomPreference: const MinMaxZoomPreference(14, 17), ), ), CarouselSlider( items: carouselItems, options: CarouselOptions( height: 105, viewportFraction: 0.6, initialPage: 0, enableInfiniteScroll: false, scrollDirection: Axis.horizontal, onPageChanged: (int index, CarouselPageChangedReason reason) { setState(() { pageIndex = index; }); _addSourceAndLineLayer(index, true); }, ), ) ], ), ), floatingActionButton: FloatingActionButton( onPressed: () { controller?.animateCamera( CameraUpdate.newCameraPosition(_initialCameraPosition), ); }, child: const Icon(Icons.my_location), ), ), ); } void _onMapCreated(MapboxMapController mapController) { controller = mapController; } @override void dispose() { // 页面销毁前强制禁用定位,双重保险 controller?.setMyLocationEnabled(false); super.dispose(); }
额外说明
- 用
Future.delayed等待一帧是为了确保setState触发的组件重建完成,Mapbox已经更新了myLocationEnabled的状态; - 在
dispose中调用controller.setMyLocationEnabled(false)是直接通过Mapbox控制器操作原生层,避免页面销毁时定位资源未正确释放;
内容的提问来源于stack exchange,提问作者Bart Stencil
相关产品推荐
相关产品推荐

