[英]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.