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..."),),),);
}
},
);
}
}
Error Im getting is :
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>