为啥我在flutter_web中更新HtmlView时得到_state!= _PlatformViewState.disposed不是真正的异常?
Posted
技术标签:
【中文标题】为啥我在flutter_web中更新HtmlView时得到_state!= _PlatformViewState.disposed不是真正的异常?【英文标题】:Why do I get _state != _PlatformViewState.disposed is not true exception while updating HtmlView in flutter_web?为什么我在flutter_web中更新HtmlView时得到_state!= _PlatformViewState.disposed不是真正的异常? 【发布时间】:2019-12-31 01:44:02 【问题描述】:我正在尝试使用 htmlView 在我的 flutter_web 应用程序中显示 Google 地图,但在标记更改时无法可靠地更新地图。它有一半的时间工作正常。请看下面的代码。我订阅了 InitState() 中的标记更改。当标记数据更新并侦听返回时,我每隔一段时间就会得到 _state != _PlatformViewState.disposed 异常,并且每隔一段时间就会工作一次。
查看 Flutter_web Platform View 代码,似乎每次使用不同的 ViewType 创建新的 HtmlView 时都会释放以前的 HtmlView。重绘逻辑似乎有问题,因为这个异常发生在视图被处理之后。此异常后的构建调用成功呈现 HtmlView。
══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following assertion was thrown building HtmlView(dependencies: [Directionality], state:
_HtmlViewState#705f2):
Assertion failed: org-dartlang-app:///packages/flutter_web/src/services/platform_views.dart:789:12
_state != _PlatformViewState.disposed
is not true
Either the assertion indicates an error in the framework itself, or we should provide substantially
more information in this error message to help you determine and fix the underlying cause.
In either case, please report this assertion by filing a bug on GitHub:
https://github.com/flutter/flutter/issues/new?template=BUG.md
When the exception was thrown, this was the stack:
dart:sdk_internal 4543:15 assertFailed
removeOnPlatformViewCreatedListener
package:flutter_web/…/services/platform_views.dart:789
package:flutter_web/src%5Crendering%5Cplatform_view.dart 471:21 set viewController
updateRenderObject (package:flutter_web/src%5Cwidgets%5Cplatform_view.dart:752:17)
update (package:flutter_web/src%5Cwidgets%5Cframework.dart:4670:12)
updateChild (package:flutter_web/src%5Cwidgets%5Cframework.dart:2896:14)
performRebuild (package:flutter_web/src%5Cwidgets%5Cframework.dart:3908:16)
rebuild (package:flutter_web/src%5Cwidgets%5Cframework.dart:3713:5)
update (package:flutter_web/src%5Cwidgets%5Cframework.dart:4055:5)
updateChild (package:flutter_web/src%5Cwidgets%5Cframework.dart:2896:14)
update (package:flutter_web/src%5Cwidgets%5Cframework.dart:5069:14)
updateChild (package:flutter_web/src%5Cwidgets%5Cframework.dart:2896:14)
performRebuild (package:flutter_web/src%5Cwidgets%5Cframework.dart:3908:16)
rebuild (package:flutter_web/src%5Cwidgets%5Cframework.dart:3713:5)
update (package:flutter_web/src%5Cwidgets%5Cframework.dart:3953:5)
updateChild (package:flutter_web/src%5Cwidgets%5Cframework.dart:2896:14)
updateChildren (package:flutter_web/src%5Cwidgets%5Cframework.dart:4769:32)
update (package:flutter_web/src%5Cwidgets%5Cframework.dart:5186:17)
updateChild (package:flutter_web/src%5Cwidgets%5Cframework.dart:2896:14)
performRebuild (package:flutter_web/src%5Cwidgets%5Cframework.dart:3908:16)
rebuild (package:flutter_web/src%5Cwidgets%5Cframework.dart:3713:5)
update (package:flutter_web/src%5Cwidgets%5Cframework.dart:4164:5)
updateChild (package:flutter_web/src%5Cwidgets%5Cframework.dart:2896:14)
performRebuild (package:flutter_web/src%5Cwidgets%5Cframework.dart:3908:16)
rebuild (package:flutter_web/src%5Cwidgets%5Cframework.dart:3713:5)
update (package:flutter_web/src%5Cwidgets%5Cframework.dart:4164:5)
updateChild (package:flutter_web/src%5Cwidgets%5Cframework.dart:2896:14)
updateChildren (package:flutter_web/src%5Cwidgets%5Cframework.dart:4769:32)
update (package:flutter_web/src%5Cwidgets%5Cframework.dart:5186:17)
updateChild (package:flutter_web/src%5Cwidgets%5Cframework.dart:2896:14)
performRebuild (package:flutter_web/src%5Cwidgets%5Cframework.dart:3908:16)
rebuild (package:flutter_web/src%5Cwidgets%5Cframework.dart:3713:5)
update (package:flutter_web/src%5Cwidgets%5Cframework.dart:4055:5)
updateChild (package:flutter_web/src%5Cwidgets%5Cframework.dart:2896:14)
performRebuild (package:flutter_web/src%5Cwidgets%5Cframework.dart:3908:16)
rebuild (package:flutter_web/src%5Cwidgets%5Cframework.dart:3713:5)
update (package:flutter_web/src%5Cwidgets%5Cframework.dart:4164:5)
updateChild (package:flutter_web/src%5Cwidgets%5Cframework.dart:2896:14)
performRebuild (package:flutter_web/src%5Cwidgets%5Cframework.dart:3908:16)
rebuild (package:flutter_web/src%5Cwidgets%5Cframework.dart:3713:5)
update (package:flutter_web/src%5Cwidgets%5Cframework.dart:4055:5)
updateChild (package:flutter_web/src%5Cwidgets%5Cframework.dart:2896:14)
update (package:flutter_web/src%5Cwidgets%5Cframework.dart:5069:14)
updateChild (package:flutter_web/src%5Cwidgets%5Cframework.dart:2896:14)
performRebuild (package:flutter_web/src%5Cwidgets%5Cframework.dart:3908:16)
rebuild (package:flutter_web/src%5Cwidgets%5Cframework.dart:3713:5)
update (package:flutter_web/src%5Cwidgets%5Cframework.dart:3953:5)
updateChild (package:flutter_web/src%5Cwidgets%5Cframework.dart:2896:14)
update (package:flutter_web/src%5Cwidgets%5Cframework.dart:5069:14)
updateChild (package:flutter_web/src%5Cwidgets%5Cframework.dart:2896:14)
performRebuild (package:flutter_web/src%5Cwidgets%5Cframework.dart:3908:16)
rebuild (package:flutter_web/src%5Cwidgets%5Cframework.dart:3713:5)
update (package:flutter_web/src%5Cwidgets%5Cframework.dart:4164:5)
updateChild (package:flutter_web/src%5Cwidgets%5Cframework.dart:2896:14)
performRebuild (package:flutter_web/src%5Cwidgets%5Cframework.dart:3908:16)
rebuild (package:flutter_web/src%5Cwidgets%5Cframework.dart:3713:5)
update (package:flutter_web/src%5Cwidgets%5Cframework.dart:4055:5)
updateChild (package:flutter_web/src%5Cwidgets%5Cframework.dart:2896:14)
performRebuild (package:flutter_web/src%5Cwidgets%5Cframework.dart:3908:16)
rebuild (package:flutter_web/src%5Cwidgets%5Cframework.dart:3713:5)
buildScope (package:flutter_web/src%5Cwidgets%5Cframework.dart:2347:31)
drawFrame (package:flutter_web/src%5Cwidgets%5Cbinding.dart:710:49)
[_handlePersistentFrameCallback] (package:flutter_web/src%5Crendering%5Cbinding.dart:286:5)
[_invokeFrameCallback]
package:flutter_web/…/scheduler/binding.dart:1030
handleDrawFrame
package:flutter_web/…/scheduler/binding.dart:963
[_handleDrawFrame]
package:flutter_web/…/scheduler/binding.dart:874
<fn> (package:flutter_web_ui/src%5Cengine.dart:164:21)
════════════════════════════════════════════════════════════════════════════════════════════════════
class Panics extends StatefulWidget
final bool selectOnly;
final bool showAddButton;
final bool boListGrid;
final bool boShowAppBar;
Panics(this.selectOnly,
[this.showAddButton = true,
this.boListGrid = true,
this.boShowAppBar = true]);
@override
_PanicsState createState() =>
_PanicsState(selectOnly, showAddButton, boListGrid, boShowAppBar);
class _PanicsState extends State<Panics>
final bool selectOnly;
final bool showAddButton;
final bool boListGrid;
final bool boShowAppBar;
String createdViewId = 'hello-world-html';
String strMap;
bool inProgress = true;
// Subscription
StreamSubscription subscription;
List<fs.DocumentSnapshot> panics;
Map<String, bool> boShowGrid;
List<fs.DocumentReference> isSelected;
final key = GlobalKey<ScaffoldState>();
// final _foldingCellKey = GlobalKey<SimpleFoldingCellState>();
_PanicsState(
this.selectOnly, this.showAddButton, this.boListGrid, this.boShowAppBar);
@override
void initState()
debugPrint("PANICS: initState");
// TODO: implement initState
isSelected = List<fs.DocumentReference>();
boShowGrid = Map<String, bool>();
showPanics(null);
fs.Query ref;
if (Globals.role == Role.Manager)
// Make a reference to firestore
ref = firestore()
.collection('locations')
.where("hotelId", "==", Globals.hotelID);
else
// Make a reference to firestore
ref = firestore()
.collection('locations')
.where("userId", "==", Globals.userId);
ref = ref.where("status", "==", "new");
subscription = ref.onSnapshot.listen((data)
showPanics(data.docs);
);
super.initState();
void showPanics(List<fs.DocumentSnapshot> panics)
String markers = "";
String latlng = "var myLatLng = lat: 41.850033, lng: -87.6500523";
DateTime max = DateTime.fromMicrosecondsSinceEpoch(0);
fs.GeoPoint lastPanicPosition;
if (panics != null)
panics.forEach((data)
Panic panic = Panic.fromSnapshot(data);
String strIcon = (panic.status == 'new')?"http://maps.google.com/mapfiles/ms/icons/red-dot.png":"http://maps.google.com/mapfiles/ms/icons/green-dot.png";
String marker =
"var marker = new google.maps.Marker(position: new google.maps.LatLng($panic.position.latitude, $panic.position.longitude),"
+ "map: map, icon:"$strIcon", title: '$Globals.globals.getUserName(panic.userId) needs help!');\n";
markers += marker;
DateTime time = panic.timeStamp;
if (time.compareTo(max) > 0 )
max = time;
lastPanicPosition = panic.position;
);
latlng = "var myLatLng = lat: $lastPanicPosition.latitude, lng: $lastPanicPosition.longitude";
debugPrint("Panics: showPanic markers = $markers");
debugPrint("Panics: showPanic latlng = $latlng");
String createdViewUpdate = DateTime.now().toString();
rootBundle.loadString('map.html').then((value)
String strMapUpdate = value.replaceAll(new RegExp(r'var myLatLng = lat: 41.850033, lng: -87.6500523'), latlng);
strMapUpdate = strMapUpdate.replaceAll(new RegExp(r'markers'), markers);
debugPrint ("Panics strMapUpdate =: $strMapUpdate");
ui.platformViewRegistry.registerViewFactory(
createdViewId,
(int viewId) => IFrameElement()
..width = (MediaQuery.of(context).size.width - 400).toString()
..height = MediaQuery.of(context).size.height.toString()
..srcdoc = strMapUpdate
..style.border = 'none');
);
if ((panics != null)&&(mounted))
setState(()
inProgress = false;
this.createdViewId = createdViewUpdate;
this.panics = panics;
);
@override
Widget build(BuildContext context)
debugPrint("Panics build");
return (((Globals.globals == null) || (Globals.documentID == null))
//Uncomment this to use roomList
// ||(Globals.roomList.isEmpty)
)
? Scaffold(body: Text("Loading..."))
: (selectOnly)
? Scaffold(
key: key,
appBar: AppBar(title: Text(Globals.hotelName + ":Alerts")),
body: _buildBody(context),
)
: (showAddButton)
? Scaffold(
floatingActionButton: FloatingActionButton(
heroTag: "panic",
backgroundColor: Colors.greenAccent,
mini: true,
child: Icon(Icons.person),
onPressed: () => setState(()
_deletePanics(context);
),
),
floatingActionButtonLocation:
FloatingActionButtonLocation.endFloat,
appBar: (boShowAppBar)
? AppBar(
title: Text(
(boListGrid) ? "Alerts list" : "Alerts grid"))
: null,
body: Row (
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width - 400,
child: HtmlView(
viewType: createdViewId,
onPlatformViewCreated: _onPlatformViewCreated,
)),
Container(
width: 400,
child: _buildBody(context),
)
]
)
)
: (boShowAppBar)
? Scaffold(
appBar: AppBar(title: Text("Panics")),
body: _buildBody(context),
)
: Scaffold(
body: _buildBody(context),
);
【问题讨论】:
我也得到了这个,但是通过在重新创建 htmlview 之前不重新加载小部件来解决它。你在flutter上登录了吗? 谢谢。我没有在flutter上记录它,因为我找不到为flutter web提交问题的方法。但我使用下面答案中的方法让它运作良好。 【参考方案1】:我能够通过在构建 HtmlView 之前将对 ui.platformViewRegistry.registerViewFactory 的调用移动到构建函数来解决此问题。我不得不通过将 HtmlView 包装到 FutureBuilder 小部件中来延迟 HtmlView 的重新加载,以允许构建函数有时间从 Firebase 获取标记信息。见下面的代码
@override
Widget build(BuildContext context)
debugPrint("Panics: build: boShowAppBar = $boShowAppBar ");
//showPanics(null);
return (((Globals.globals == null) || (Globals.documentID == null))
//Uncomment this to use roomList
// ||(Globals.roomList.isEmpty)
)
? Scaffold(body: Text("Loading..."))
: (selectOnly)
? Scaffold(
key: key,
appBar: AppBar(title: Text(Globals.hotelName + ":Alerts")),
body: _buildBody(context),
)
: Scaffold(
floatingActionButton: (showAddButton) ? FloatingActionButton(
heroTag: "panic",
backgroundColor: Colors.greenAccent,
mini: true,
child: Icon(Icons.delete),
tooltip: "Delete selected",
onPressed: () => setState(()
_deletePanics(context);
),
):null,
floatingActionButtonLocation:
FloatingActionButtonLocation.endFloat,
appBar: (boShowAppBar)
? AppBar(
title: Text(
(boListGrid) ? "Alerts list" : "Alerts grid"),
actions: <Widget>[
FlatButton(
onPressed: () => setState(()
_deletePanics(context);
),
child: Text("Delete selected",
style: TextStyle(color: Colors.white))),
],
)
: null,
body: Row(children: <Widget>[
Container(
width: 400,
child: _buildBody(context),
),
Container(
width: MediaQuery.of(context).size.width - 400,
child: FutureBuilder(
future: Future.delayed(Duration(seconds: 1)),
builder: (c,s) => (s.connectionState == ConnectionState.done)?showMap():Container(),)
)
]));
Widget showMap()
debugPrint("PANICS: showMap()");
showPanics(this.panics);
return HtmlView( viewType: createdViewId,
onPlatformViewCreated: _onPlatformViewCreated,
);
【讨论】:
“registerViewFactory”在哪里?它不在此代码中。以上是关于为啥我在flutter_web中更新HtmlView时得到_state!= _PlatformViewState.disposed不是真正的异常?的主要内容,如果未能解决你的问题,请参考以下文章
为啥不更新我在子组件中传递的父组件中的值并更新使用自定义事件 $emit Vue 3?
为啥我在 put 请求中的更新会覆盖 Sequelize 中的整个记录?
为啥当我在 Flutter for Web 中更新实时数据库中的某个字段时我的数据被删除
跳过编译 flutter_web|web/main.dart] 因为它的一些库有这个平台不支持的 sdk 依赖项