Flutter GoogleMap从后台恢复后是空白的



我遇到了以下问题:我的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;
}
}

步骤03 为初始化状态添加此内容

WidgetsBinding.instance!.addObserver(this);

步骤 04 第 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实现解决方案。无需更改任何其他内容: 导入颤振服务:

import 'package:flutter/services.dart';

法典:

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

这里的"mapController"是你在代码中某处命名的谷歌地图控制器的实例。就我而言,它是这样的:

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('nndidChangeAppLifecycleState');

if (state == AppLifecycleState.resumed) {
final GoogleMapController controller1 = await controller.future;
controller1.setMapStyle('[]');
}

}


void initState() {                             

super.initState();

WidgetsBinding.instance!.addObserver(this);
}

另一个不需要分叉插件、构建等的临时修复
添加一个通过WidgetsBindingObserver实现的didChangeAppLifecycleState到你的小部件中,并通过状态更改重建谷歌地图小部件。

就我而言,地图在调用setState时会抛出黑屏,以下解决方案解决了我的问题。

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

相关内容

  • 没有找到相关文章

最新更新