我来自 Android 开发,对 Flutter 开发非常陌生,我遇到过用于状态管理的 ScopedModel 和 Provider,并且我选择 Provider 作为我的用例。我的用例是登录后,仪表板应该用数据呈现。我创建了一个扩展 ChangeNotifier 的 ViewModel,并希望使用它,以便我可以在不同的小部件之间重用此数据。我不完全确定如何使用我的 ViewModel 来加载小部件的数据。有人可以帮助我制定正确的设计模式吗?
\n\nabstract class ViewModel extends ChangeNotifier {\n}\n\nclass EventViewModel extends ViewModel {\n EventDataState _eventDataState = EventDataUnInitialized();\n\n EventDataState get eventDataState => _eventDataState;\n\n set eventDataState(EventDataState value) {\n _eventDataState = value;\n notifyListeners();\n }\n\n gatherEvents() {\n eventDataState = EventDataLoading();\n EventService.create().getEvents().then((data){\n var responseData = json.decode(data.bodyString);\n eventDataState = EventDataLoaded(\n responseData.map((each) => new EventData.fromJson(each)).toList());\n }).catchError((err){\n eventDataState = EventDataLoadFailed("Failed to do something");\n });\n }\n}\n\n\nclass DashboardPage extends StatefulWidget {\n static const routename = "/dashboard";\n\n @override\n _DashboardPageState createState() => _DashboardPageState();\n}\n\n class _DashboardPageState extends State<DashboardPage> {\n\n @override\n Widget build(BuildContext context) {\n return Consumer<EventViewModel>(\n builder: (context, vm, child) {\n if (vm.eventDataState is EventDataUnInitialized) {\n vm.gatherEvents();\n return Scaffold(body: Container(),);\n }else if (vm.eventDataState is EventDataLoading) {\n return Scaffold(body: Container(child: Center(child: CircularProgressIndicator(),),),);\n }else if (vm.eventDataState is EventDataLoadFailed) {\n return Scaffold(body: Container(child: Center(child: Text("Error Loading Data."),),),);\n }else{\n return Scaffold(body: Container(child: Center(child: Text("Data done loading..."),),),);\n }\n },\n );\n }\n }\nRun Code Online (Sandbox Code Playgroud)\n\n我得到的错误是:
\n\nI/flutter (30492): \xe2\x95\x90\xe2\x95\x90\xe2\x95\xa1 EXCEPTION CAUGHT BY FOUNDATION LIBRARY \xe2\x95\x9e\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\nI/flutter (30492): The following assertion was thrown while dispatching notifications for EventViewModel:\nI/flutter (30492): setState() or markNeedsBuild() called during build.\nI/flutter (30492): This ListenableProvider<EventViewModel> widget cannot be marked as needing to build because the\nI/flutter (30492): framework is already in the process of building widgets. A widget can be marked as needing to be\nI/flutter (30492): built during the build phase only if one of its ancestors is currently building. This exception is\nI/flutter (30492): allowed because the framework builds parent widgets before children, which means a dirty descendant\nI/flutter (30492): will always be built. Otherwise, the framework might not visit this widget during this build phase.\nI/flutter (30492): The widget on which setState() or markNeedsBuild() was called was:\nI/flutter (30492): ListenableProvider<EventViewModel>\nI/flutter (30492): The widget which was currently being built when the offending call was made was:\nI/flutter (30492): Consumer<EventViewModel>\nRun Code Online (Sandbox Code Playgroud)\n
您可以使用 SchedulerBinding 来防止此异常:
替代方案 1:
initState() {
super.initState();
final gatherEvents =
Provider.of<EventViewModel>(context, listen: false).gatherEvents;
SchedulerBinding.instance.addPostFrameCallback((_) => gatherEvents());
}
Run Code Online (Sandbox Code Playgroud)
替代方案 2:
initState() {
super.initState();
Future.microtask(() =>
Provider.of<EventViewModel>(context, listen: false).gatherEvents();
);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4558 次 |
| 最近记录: |