initialize data once in initState and call the setState when data is ready causes exception

后端 未结 4 1498
清酒与你
清酒与你 2021-01-11 10:39

Since flutter calls the build method many times in different condition, to avoid getting the data many times, I initialize the data in initState.

I want

相关标签:
4条回答
  • 2021-01-11 10:39

    an alternative is to put it inside PostFrameCallback which is between initState and Build.

      @override
      void initState() {
        WidgetsBinding.instance.addPostFrameCallback((_) => getData());
        super.initState();
      }
    
      getData() async {
    
      }
    
    0 讨论(0)
  • 2021-01-11 10:44

    For everyone coming here at a later point

    It is best to use the @override void didChangeDependencies () method of the State class.

    From the docs

    This method is also called immediately after initState. It is safe to call BuildContext.inheritFromWidgetOfExactType from this method.

    But make sure to check if you have already performed your initialization

    @override
    void didChangeDependencies() {
      super.didChangeDependencies();
      if (bloc == null) { // or else you end up creating multiple instances in this case.
        bloc = BlocProvider<MyBloc>.of(context);
      }
    }
    
    0 讨论(0)
  • Edit: Better answer below.


    Apparently, you cannot access getData(context) during initState (more concrete: before it completed).

    The reason, so I believe, is that getData tries to look up an InheritedWidget ancestor up in the tree, but the tree is just now being built (your widget is created during the parent widget's build).

    The obvious solution would be to delay getData's lookup to a later point in time. There are several ways to achieve that:

    • Delay the lookup to a later time. scheduleMicrotask should work fine.
    • Look it up during the first build call. You could have an isInitialized field set to false and in you build, something like:

      if (!isInitialized) {
        isInitialized = true;
        // TODO: do the getData(...) stuff
      }
      
    0 讨论(0)
  • 2021-01-11 10:59

    I moved my code to my build method from initState and it worked

    class _TestState extends State<Test> {
    
      Data data;
      bool dataReady = false;
    
      @override
      void initState() {
        super.initState();
    
      }
    
      @override
      Widget build(BuildContext context) {
        getData(context).then((Data data) async {
          setState(() {
            dataReady= true;
          });
        });
        if (dataReady) {
          return createMainContent(context);
        } else {
          return new Container();
        }
      }
    
    }
    
    0 讨论(0)
提交回复
热议问题