使用提供程序在onLoad上获取数据 [英] Using provider in fetching data onLoad

查看:92
本文介绍了使用提供程序在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆