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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 00:03:18