Flutter Google Maps渲染器热重启重复初始化异常求助
问题描述
我使用google_maps_flutter_android: ^2.6.0尝试启用Flutter Google Maps的最新地图渲染器,初始代码如下:
main() async { ... AndroidMapRenderer mapRenderer = AndroidMapRenderer.platformDefault; final GoogleMapsFlutterPlatform mapsImplementation = GoogleMapsFlutterPlatform.instance; if (mapsImplementation is GoogleMapsFlutterAndroid) { WidgetsFlutterBinding.ensureInitialized(); mapRenderer = await mapsImplementation.initializeWithRenderer(AndroidMapRenderer.latest); ... runApp(MyApp); }
首次运行正常,但官方文档明确说明:
The renderer must be requested before creating GoogleMap instances, as the renderer can be initialized only once per application context.
(译文:渲染器必须在创建GoogleMap实例前请求,每个应用上下文仅能初始化一次渲染器。)
因此每次热重启时,都会抛出异常:
PlatformException (PlatformException(Renderer already initialized, Renderer initialization called multiple times, null, null))
我尝试用try-catch捕获异常,但仍会抛出异常导致应用暂停,修改后的代码如下:
main() async { ... AndroidMapRenderer mapRenderer = AndroidMapRenderer.platformDefault; try { final GoogleMapsFlutterPlatform mapsImplementation = GoogleMapsFlutterPlatform.instance; if (mapsImplementation is GoogleMapsFlutterAndroid) { WidgetsFlutterBinding.ensureInitialized(); mapRenderer = await mapsImplementation.initializeWithRenderer(AndroidMapRenderer.latest); } } catch (e) { log(e.toString()); } ... runApp(MyApp); }
请问有没有办法让这段初始化代码仅执行一次,即使热重启也不重复运行?
解决方案
方法1:检查当前渲染器状态再初始化
利用GoogleMapsFlutterAndroid提供的getRenderer()方法,先获取当前已生效的渲染器,仅当它不是最新版时才执行初始化操作:
main() async { // 必须先初始化绑定,确保异步操作正常执行 WidgetsFlutterBinding.ensureInitialized(); AndroidMapRenderer mapRenderer = AndroidMapRenderer.platformDefault; final GoogleMapsFlutterPlatform mapsImplementation = GoogleMapsFlutterPlatform.instance; if (mapsImplementation is GoogleMapsFlutterAndroid) { // 获取当前已初始化的渲染器 final currentRenderer = await mapsImplementation.getRenderer(); if (currentRenderer != AndroidMapRenderer.latest) { try { mapRenderer = await mapsImplementation.initializeWithRenderer(AndroidMapRenderer.latest); } catch (e) { log("渲染器初始化失败: $e"); } } else { // 已使用最新渲染器,直接复用 mapRenderer = currentRenderer; } } runApp(const MyApp()); }
方法2:用持久化存储标记初始化状态
使用SharedPreferences存储初始化成功的标记,因为持久化存储在热重启后不会丢失:
import 'package:shared_preferences/shared_preferences.dart'; import 'package:flutter/foundation.dart'; import 'package:google_maps_flutter_android/google_maps_flutter_android.dart'; import 'package:google_maps_flutter_platform_interface/google_maps_flutter_platform_interface.dart'; main() async { WidgetsFlutterBinding.ensureInitialized(); final prefs = await SharedPreferences.getInstance(); // 定义持久化标记的key const String initializedKey = 'has_initialized_latest_renderer'; AndroidMapRenderer mapRenderer = AndroidMapRenderer.platformDefault; final GoogleMapsFlutterPlatform mapsImplementation = GoogleMapsFlutterPlatform.instance; if (mapsImplementation is GoogleMapsFlutterAndroid) { // 检查是否已初始化过最新渲染器 bool hasInitialized = prefs.getBool(initializedKey) ?? false; if (!hasInitialized) { try { mapRenderer = await mapsImplementation.initializeWithRenderer(AndroidMapRenderer.latest); // 标记初始化成功 await prefs.setBool(initializedKey, true); } catch (e) { log("渲染器初始化失败: $e"); } } else { // 已初始化,直接获取当前渲染器 mapRenderer = await mapsImplementation.getRenderer(); } } runApp(const MyApp()); }
方法3:修复try-catch的作用范围
你之前的try-catch未生效,可能是因为WidgetsFlutterBinding.ensureInitialized()放在了if块内,导致异步操作环境未准备好。将binding初始化移到main函数最开头,并确保try-catch覆盖整个初始化逻辑:
main() async { WidgetsFlutterBinding.ensureInitialized(); AndroidMapRenderer mapRenderer = AndroidMapRenderer.platformDefault; try { final GoogleMapsFlutterPlatform mapsImplementation = GoogleMapsFlutterPlatform.instance; if (mapsImplementation is GoogleMapsFlutterAndroid) { mapRenderer = await mapsImplementation.initializeWithRenderer(AndroidMapRenderer.latest); } } on PlatformException catch (e) { // 明确捕获平台异常 if (e.code == 'Renderer already initialized') { // 若已初始化,直接获取当前渲染器 final mapsImplementation = GoogleMapsFlutterPlatform.instance as GoogleMapsFlutterAndroid; mapRenderer = await mapsImplementation.getRenderer(); } else { log("未知异常: $e"); } } catch (e) { log("其他异常: $e"); } runApp(const MyApp()); }
内容的提问来源于stack exchange,提问作者rhnzal
相关产品推荐
相关产品推荐

