我很难找到此异常的来源,而且该应用程序非常复杂,因此很难显示代码的任何相关部分。这是发生错误时的存储库: Github repo
我怀疑以下代码可能是肇事者:
Widget buildResultCard(Map result, BuildContext context) { String name = result["value"]; String description = result["label"].replaceAll(new RegExp(r"<(?:.|\n)*?>"), ""); TextEditingController controller = new TextEditingController(text: name); Function onPressed = () { showDialog( context: context, child: new AlertDialog( title: new Text("Name your schedule"), content: new TextField( autofocus: true, controller: controller, ), actions: <Widget>[ new FlatButton( onPressed: () { String givenName = controller.text; ScheduleMeta schedule = new ScheduleMeta( givenName: givenName, name: name, type: _selectedChoice.value, description: description); scheduleStore .dispatch(new AddScheduleAction(schedule: schedule)); scheduleStore.dispatch( new SetCurrentScheduleAction(schedule: schedule)); fetchAllSchedules(scheduleStore.state.schedules) .then((weeks) { scheduleStore.dispatch( new SetWeeksForCurrentScheduleAction(weeks: weeks)); }); Scaffold.of(context).showSnackBar(new SnackBar( content: new Text("Added " + givenName), action: new SnackBarAction( label: "Undo", onPressed: () { scheduleStore.dispatch( new RemoveScheduleAction(schedule: name)); Scaffold.of(context).showSnackBar(new SnackBar( content: new Text( "Deleted " + givenName), )); }), )); Navigator.of(context).pop(); }, child: new Text("Add")), ], )); }; return new Card( child: new Column( mainAxisSize: MainAxisSize.min, children: <Widget>[ new ListTile( leading: const Icon(Icons.schedule), title: new Text(name), subtitle: new Text(description), isThreeLine: true, dense: true, ), new ButtonTheme.bar( child: new ButtonBar( children: <Widget>[ new FlatButton( child: const Text('Add Schedule'), onPressed: scheduleStore.state.schedules .any((schedule) => schedule.name == name) ? null : onPressed) ], ), ), ], ), ); }
显示对话框时出现错误,并且当用户按下对话框上的按钮时,两个Redux存储调度将彼此直接发送。对话框后面的UI订阅Redux存储中的更改。
我以为Dart / Flutter是单线程的,因此不会发生这样的冲突,在这种情况下,似乎线程在小部件上调用setState(),而另一个在小部件树上锁定了。
有没有一种方法可以检查小部件树是否被锁定,从而可以避免这种情况?
堆栈提供此信息:
I/flutter (13466): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════ I/flutter (13466): The following assertion was thrown while finalizing the widget tree: I/flutter (13466): setState() or markNeedsBuild() called when widget tree was locked. I/flutter (13466): This _ModalScope widget cannot be marked as needing to build because the framework is locked. I/flutter (13466): The widget on which setState() or markNeedsBuild() was called was: I/flutter (13466): _ModalScope([LabeledGlobalKey<_ModalScopeState>#cb4cc]; state: _ModalScopeState#d4c02()) I/flutter (13466): I/flutter (13466): When the exception was thrown, this was the stack: I/flutter (13466): #0 Element.markNeedsBuild.<anonymous closure> (package:flutter/src/widgets/framework.dart:3250) I/flutter (13466): #2 Element.markNeedsBuild (package:flutter/src/widgets/framework.dart:3226) I/flutter (13466): #3 State.setState (package:flutter/src/widgets/framework.dart:1072) I/flutter (13466): #4 _ModalScopeState._routeSetState (package:flutter/src/widgets/routes.dart:473) I/flutter (13466): #5 ModalRoute.setState (package:flutter/src/widgets/routes.dart:552) I/flutter (13466): #6 ModalRoute.changedInternalState (package:flutter/src/widgets/routes.dart:889) I/flutter (13466): #7 TransitionRoute&&LocalHistoryRoute.removeLocalHistoryEntry (package:flutter/src/widgets/routes.dart:317) I/flutter (13466): #8 LocalHistoryEntry.remove (package:flutter/src/widgets/routes.dart:267) I/flutter (13466): #9 DrawerControllerState.dispose (package:flutter/src/material/drawer.dart:147) I/flutter (13466): #10 StatefulElement.unmount (package:flutter/src/widgets/framework.dart:3550) I/flutter (13466): #11 _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1626) I/flutter (13466): #12 _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1624) I/flutter (13466): #13 ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:3427) I/flutter (13466): #14 _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1622) I/flutter (13466): #15 _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1624) I/flutter (13466): #16 MultiChildRenderObjectElement.visitChildren (package:flutter/src/widgets/framework.dart:4421) I/flutter (13466): #17 _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1622) I/flutter (13466): #18 _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1624) I/flutter (13466): #19 ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:3427) I/flutter (13466): #20 _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1622) I/flutter (13466): #21 _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1624) I/flutter (13466): #22 ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:3427) I/flutter (13466): #23 _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1622) I/flutter (13466): #24 _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1624) I/flutter (13466): #25 SingleChildRenderObjectElement.visitChildren (package:flutter/src/widgets/framework.dart:4321) I/flutter (13466): #26 _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1622) I/flutter (13466): #27 _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1624) I/flutter (13466): #28 ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:3427) I/flutter (13466): #29 _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1622) I/flutter (13466): #30 _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1624) I/flutter (13466): #31 SingleChildRenderObjectElement.visitChildren (package:flutter/src/widgets/framework.dart:4321) I/flutter (13466): #32 _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1622) I/flutter (13466): #33 _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1624) I/flutter (13466): #34 ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:3427) I/flutter (13466): #35 _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1622) I/flutter (13466): #36 _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1624) I/flutter (13466): #37 ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:3427) I/flutter (13466): #38 _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1622) I/flutter (13466): #39 _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1624) I/flutter (13466): #40 ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:3427) I/flutter (13466): #41 _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1622) I/flutter (13466): #42 _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1624) I/flutter (13466): #43 ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:3427) I/flutter (13466): #44 _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1622) I/flutter (13466): #45 _InactiveElements._unmount.<anonymous closure> (package:flutter/src/widgets/framework.dart:1624) I/flutter (13466): #46 ComponentElement.visitChildren (package:flutter/src/widgets/framework.dart:3427) I/flutter (13466): #47 _InactiveElements._unmount (package:flutter/src/widgets/framework.dart:1622) I/flutter (13466): #48 _InactiveElements._unmountAll (package:flutter/src/widgets/framework.dart:1636) I/flutter (13466): #49 BuildOwner.finalizeTree.<anonymous closure> (package:flutter/src/widgets/framework.dart:2228) I/flutter (13466): #50 BuildOwner.lockState (package:flutter/src/widgets/framework.dart:2060) I/flutter (13466): #51 BuildOwner.finalizeTree (package:flutter/src/widgets/framework.dart:2227) I/flutter (13466): #52 BindingBase&SchedulerBinding&GestureBinding&ServicesBinding&RendererBinding&WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:505) I/flutter (13466): #53 BindingBase&SchedulerBinding&GestureBinding&ServicesBinding&RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:189) I/flutter (13466): #54 BindingBase&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:688) I/flutter (13466): #55 BindingBase&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:636) I/flutter (13466): #56 _drawFrame (file:///b/build/slave/Linux_Engine/build/src/flutter/lib/ui/hooks.dart:70) I/flutter (13466): (elided one frame from class _AssertionError) I/flutter (13466): ════════════════════════════════════════════════════════════════════════════════════════════════════
这不是线程问题。此错误表示您setState在构建阶段正在调用。
setState
一个典型的例子如下:
Widget build(BuildContext context) { myParentWidgetState.setState(() { print("foo"); }); return Container(); }
但是setState调用可能不太明显。例如,a Navigator.pop(context)在setState内部执行。因此,以下内容:
Navigator.pop(context)
Widget build(BuildContext context) { Navigator.pop(context); return Container(); }
也不行。
查看stacktrace,似乎与Navigator.pop(context) 模态同时尝试使用新数据进行更新。