使用提供程序在onLoad上获取数据 [英] Using provider in fetching data onLoad
问题描述
我来自Android开发,是Flutter开发的新手,我遇到了ScopedModel和State Management的Provider,并为我的用例选择了Provider.我的用例是登录后,仪表板应该用数据呈现.我创建了一个扩展ChangeNotifier的ViewModel,并希望使用它,以便可以在不同的小部件之间重用此数据.我不能完全确定如何使用ViewModel加载小部件的数据.可以为我提供合适的设计模式吗?
I'm from Android development and very new to Flutter development, I have come across ScopedModel and Provider for State Management and I picked Provider for my use case. And my use case is after logging in, dashboard should be rendered with data. I have created a ViewModel that is extending ChangeNotifier, and wanted to use so that I can reuse this data across different widgets. Im not completely sure how to use my ViewModel to load data onload of the widget. Can some help me with a proper design pattern.
abstract class ViewModel extends ChangeNotifier {
}
class EventViewModel extends ViewModel {
EventDataState _eventDataState = EventDataUnInitialized();
EventDataState get eventDataState => _eventDataState;
set eventDataState(EventDataState value) {
_eventDataState = value;
notifyListeners();
}
gatherEvents() {
eventDataState = EventDataLoading();
EventService.create().getEvents().then((data){
var responseData = json.decode(data.bodyString);
eventDataState = EventDataLoaded(
responseData.map((each) => new EventData.fromJson(each)).toList());
}).catchError((err){
eventDataState = EventDataLoadFailed("Failed to do something");
});
}
}
class DashboardPage extends StatefulWidget {
static const routename = "/dashboard";
@override
_DashboardPageState createState() => _DashboardPageState();
}
class _DashboardPageState extends State<DashboardPage> {
@override
Widget build(BuildContext context) {
return Consumer<EventViewModel>(
builder: (context, vm, child) {
if (vm.eventDataState is EventDataUnInitialized) {
vm.gatherEvents();
return Scaffold(body: Container(),);
}else if (vm.eventDataState is EventDataLoading) {
return Scaffold(body: Container(child: Center(child: CircularProgressIndicator(),),),);
}else if (vm.eventDataState is EventDataLoadFailed) {
return Scaffold(body: Container(child: Center(child: Text("Error Loading Data."),),),);
}else{
return Scaffold(body: Container(child: Center(child: Text("Data done loading..."),),),);
}
},
);
}
}
我得到的错误是:
I/flutter (30492): ══╡ EXCEPTION CAUGHT BY FOUNDATION LIBRARY ╞════════════════════════════════════════════════════════
I/flutter (30492): The following assertion was thrown while dispatching notifications for EventViewModel:
I/flutter (30492): setState() or markNeedsBuild() called during build.
I/flutter (30492): This ListenableProvider<EventViewModel> widget cannot be marked as needing to build because the
I/flutter (30492): framework is already in the process of building widgets. A widget can be marked as needing to be
I/flutter (30492): built during the build phase only if one of its ancestors is currently building. This exception is
I/flutter (30492): allowed because the framework builds parent widgets before children, which means a dirty descendant
I/flutter (30492): will always be built. Otherwise, the framework might not visit this widget during this build phase.
I/flutter (30492): The widget on which setState() or markNeedsBuild() was called was:
I/flutter (30492): ListenableProvider<EventViewModel>
I/flutter (30492): The widget which was currently being built when the offending call was made was:
I/flutter (30492): Consumer<EventViewModel>
推荐答案
您可以使用SchedulerBinding阻止此异常:
You can use SchedulerBinding to prevent this exception:
替代1:
initState() {
super.initState();
final gatherEvents =
Provider.of<EventViewModel>(context, listen: false).gatherEvents;
SchedulerBinding.instance.addPostFrameCallback((_) => gatherEvents());
}
替代2:
initState() {
super.initState();
Future.microtask(() =>
Provider.of<EventViewModel>(context, listen: false).gatherEvents();
);
}
这篇关于使用提供程序在onLoad上获取数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!