繁体   English   中英

从后台恢复后,Flutter GoogleMap 为空白

[英]Flutter GoogleMap is blank after resuming from background

我遇到以下问题:我的 Flutter 应用使用 GoogleMap。 地图最初加载得很好。 但是,如果我将应用程序置于后台并稍后恢复,则地图将保持空白。 Google 徽标仍然显示,就像未指定 API 密钥时一样。 我的多边形叠加层也没有出现。

该行为不能可靠地重现。 有时,应用程序在后台运行数小时后地图加载正常,有时地图在几分钟后为空白。 到目前为止,我只在 Android 上看到过这种行为。

没有指示错误的特定日志输出。

任何想法如何解决/解决这个问题?

我在这里提出了一个截图问题: https ://github.com/flutter/flutter/issues/40284

编辑 1:我能够使用 GoogleMap 作为根小部件来重现它,并且没有任何多边形/特征覆盖。 此外,我发现在某些时候疯狂放大地图会“重新激活”地图(突然地图再次变得可见)。 这可能是底层 Android Google Maps SDK 的已知问题吗?

编辑2:我发现地图仍在反应(例如,点击/手势监听器仍然触发)。 此外,地图并不是真正的空,它只是变得半透明,因此屏幕会显示地图后面的任何小部件。

我发现如果您点击标记或更改地图重新渲染的样式

class TheWidgetThatHasTheMap with WidgetsBindingObserver {

   //...your code

    @override
    void didChangeAppLifecycleState(AppLifecycleState state) {
        if (state == AppLifecycleState.resumed) {
            controller.setMapStyle("[]");
        }
    }
}

不是核心问题的解决方案,但我能够通过创建插件项目的分支并修改 GoogleMapController.java 来解决此错误,如下所示:

@Override
  public void onActivityResumed(Activity activity) {
    if (disposed || activity.hashCode() != registrarActivityHashCode) {
      return;
    }
    mapView.onResume();
    // Workaround for https://github.com/flutter/flutter/issues/40284
    // This apparently forces a re-render of the map.
    if (googleMap != null) {
      googleMap.setMapType(googleMap.getMapType());
    }
  }

现在,在每个恢复事件中,都会重新渲染地图。

我尝试了一些东西,它似乎正在工作!

步骤01,为相关类的State类实现WidgetsBindingObserver如下,即:

class MainScreenState extends State<MainScreen> with WidgetsBindingObserver {....

步骤 02,覆盖didChangeAppLifecycleState方法,即:

@override
  Future<void> didChangeAppLifecycleState(AppLifecycleState state) async {
    super.didChangeAppLifecycleState(state);
    switch (state) {
      case AppLifecycleState.inactive:
        print('appLifeCycleState inactive');
        break;
      case AppLifecycleState.resumed:
        print('appLifeCycleState resumed');
        break;
      case AppLifecycleState.paused:
        print('appLifeCycleState paused');
        break;
      case AppLifecycleState.detached:
        print('appLifeCycleState detached');
        break;
    }
  }

Step 03 为初始化状态添加这个

WidgetsBinding.instance!.addObserver(this);

Step 04 Step 4应该如下

//onMapCreated method
  void onMapCreated(GoogleMapController controller) {
    controller.setMapStyle(Utils.mapStyles);
    _controller.complete(controller);
  }
// lifecycle
  @override
  Future<void> didChangeAppLifecycleState(AppLifecycleState state) async {
    super.didChangeAppLifecycleState(state);
    switch (state) {
      case AppLifecycleState.inactive:
        print('appLifeCycleState inactive');
        break;
      case AppLifecycleState.resumed:
        **//Add These lines**
        final GoogleMapController controller = await _controller.future;
        onMapCreated(controller);
        print('appLifeCycleState resumed');
        break;
      case AppLifecycleState.paused:
        print('appLifeCycleState paused');
        break;
      case AppLifecycleState.detached:
        print('appLifeCycleState detached');
        break;
    }
  }

在处理有状态的小部件时,将下面的代码放入您的代码中,如下所示

class MainScreenState extends State<MainScreen> with WidgetsBindingObserver 
 {....


  @override
  void initState() {
     super.initState();
     WidgetsBinding.instance!.addObserver(this);
     ...    // Other codes here 
  }


  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
       if (state == AppLifecycleState.resumed) {
         mapController!.setMapStyle("[]");
       }
    }
 }

然后您可以在状态小部件中添加以下代码

在地图小部件的全状态小部件中使用 setMapStyle 实现解决方案的另一种更简单的方法。 无需更改任何其他内容:导入 Flutter 服务:

import 'package:flutter/services.dart';

代码:

  SystemChannels.lifecycle.setMessageHandler((msg) {
      if (msg == AppLifecycleState.resumed.toString()) {
        mapController.setMapStyle("[]");
      }
    });

这里的“mapController”是您在代码中某处命名的 Google 地图控制器的实例。 就我而言,它是这样的:

  GoogleMapController _mapController;
  GoogleMapController get mapController => _mapController;
 if you facing this problem in 2022 also add this line above your class

类 YourClass 使用 WidgetsBindingObserver 扩展 StatefulWidget

Completer<GoogleMapController> controller = Completer();
    
          @override
            void dispose() {
    
              WidgetsBinding.instance!.removeObserver(this);
            
              super.dispose();
            }
              @override
              void didChangeAppLifecycleState(AppLifecycleState state) async {
                  super.didChangeAppLifecycleState(state);
                print('\n\ndidChangeAppLifecycleState');
             
                    if (state == AppLifecycleState.resumed) {
                        final GoogleMapController controller1 = await controller.future;
                        controller1.setMapStyle('[]');
                }
                
              }
        
        
          void initState() {                             
        
            super.initState();
              
            WidgetsBinding.instance!.addObserver(this);
          }

另一个不需要分叉插件、构建等的临时修复。
将通过WidgetsBindingObserver实现的didChangeAppLifecycleState添加到您的 Widget 并使用状态更改重建 GoogleMap 小部件。

在我的情况下,地图在调用 setState 时会出现黑屏,下面的解决方案解决了我的问题。

return SingleChildScrollView(
  physics: const NeverScrollableScrollPhysics(),
  child:SizedBox(
    width: MediaQuery.of(context).size.width,
    height: MediaQuery.of(context).size.height,
    child: //Your GoogleMap here,
  ),
);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM