Calling scopedModel from initState in flutter

flutter scoped model tutorial
flutter initstate not called
flutter call function on load
flutter initstate for statelesswidget
how to call function in flutter
flutter call method on statefulwidget
on start in flutter
flutter futurebuilder

I have a scopedModel class where I fetch data into it. The thing is that I'm not being able to render this data from InitState method using my scoped model where I have all my api requests. The method is being called but the inside callings are not, so my initial state of the page is not properly shown.

void initState() {
    print("Check initState");
    super.initState();
    ScopedModelDescendant<MainModel>(
        builder: (BuildContext context, Widget child, MainModel model) {
      print("Get into the scoped model");
      model.fecthCars();
      model.fecthCities();
      model.fecthBuys(model.getUserDto.token);
      print(model.getBuys().length);
      return;
    });
  }

None of the fetches(Api requests) get called. And the scopedModel returns a widget. I need this to be updated the first time I get into the manager and that's it. No need to call it again. Is this possible? or should I hardcode my api requests in each file I need?

UPDATE

If you have your scoped model class set up already you can set a Future like this inside of it

mixin MyModel on Model {
    Future<TypeToReturn> methodName(String param) async {
    Uri uri = new Uri.http('serverUrl', 'api/call');

    return await http.get(uri).then((http.Response response) {
      final List<dynamic> myResponse= json.decode(response.body);

      return myResponse;
    }).catchError((error) {
      print(error);
    });
  }
}

Aftermards you can set up your FutureBuilder

Widget _buildBody(BuildContext context, MainModel model) {

    return FutureBuilder(
      future:  model.methodName(someString), //This is the method name above
      builder: (context, AsyncSnapshot<TypeToReturn> snapshot) { //type u return
        if (!snapshot.hasData) {
          return Center(
            child: CircularProgressIndicator(),
          );
        } else {
          if (snapshot.data.length == 0)
            return Center(
              child: Text(
                "No Data Found",
                textAlign: TextAlign.center,
                style: TextStyle(
                  fontSize: 16.0,
                ),
              ),
            );

          return (create your own widget with the data inside the snapshot)
        }
      },
    );
  }

Hope this clarify things a little bit more on how I did it.

I think you've a slight misunderstanding about the point of ScopedModel and ScopedModelDescendant. The basic idea of how these should work is that the ScopedModel is created with a valid model which can then be used in other parts of the app.

However, the ScopedModelDescendant should be used within the build() function of a one of your widgets and be part of the widget tree as well. The reason your fetch methods aren't being called is that it isn't in the widget tree so the build function will never be called.

I would recommend instead moving the fetch methods out of the model and into some other class (maybe call it a communicator or controller or something). Next, I'd make it so that the model is instantiated as the result of an asynchronous call from that controller.

And finally, rather than instantiating an invalid model then changing the model once the data has been fetched, I'd recommend using a FutureBuilder - this way you have control over what to build based on whether the future is underway, successful, or failed.

So that will look something like this (pseudo-code).

StatefulWidget (MyApp or whatever you call it)
  build =>
     FutureBuilder(<fetch model data>, ...)
       (if done)
          ScopedModel<MainModel>
             .... (whatever your code has here)
               ScopedModelDescendant<MainModel>
                  (build using the model)             
       (if not done)
          Loading.... (if needed)

If you absolutely want your model to always be there, I'd still recommend doing the fetching in the top stateful widget and simply changing which model you pass in below it rather than modifying the existing model once the data is loaded.

initState method - State class - widgets library - Dart API, void initState (). @mustCallSuper, @protected. Called when this object is inserted into the tree. The framework will call this method exactly once for each State  Called when this object is inserted into the tree. The framework will call this method exactly once for each State object it creates.. Override this method to perform initialization that depends on the location at which this object was inserted into the tree (i.e., context) or on the widget used to configure this object (i.e., widget).

I stumbled upon the following solution:

In the State Class of my StatefulWidget I do:

@override
void initState() {
  super.initState();
  // and here...
  MyModel model = ScopedModel.of(context);
  // now I can do with the model whatever I need to do:
  Text someVar = model.initialText;
  model.getValuesFromSomewhere();
  // and so on
}

This, in my opinion, is the easiest way of solving the problem as stated by the original Question.

How to fetch network data in Flutter (using http and ScopedModel), However, instead of just focusing on http and placing the call in the main file, we are going to use How to fetch network data in Flutter (using http and ScopedModel) @override void initState() { super.initState(); widget.model.​fetchUsers(); } One of the most common scenarios in Mobile development is calling an async function when a new view is shown. In Flutter this can be done using a stateful widget and calling your code in the initState function.

this is my solution i hope it help

@override
  void initState() {
    super.initState();
    User user = ScopedModel.of(this.context);
    _controllerFirstName.text = user.userData['first_name'];
    _controllerLastName.text = user.userData['last_name'];
    }

Flutter Architecture-ScopedModel, A complete guide to real world , Flutter Architecture-ScopedModel, A complete guide to real world and then we'​ll make our request in the initState call of our stateful widget. Flutter Architecture-ScopedModel, A complete guide to real world architecture. In this post I will be giving direct and (hopefully) clear guidelines to writing a production ready application in Flutter using the ScopedModel architecture.

How to use load and persist json data in scoped model · Issue #11 , I am trying to load json data using the scoped model like this: import import '​package:flutter/services.dart' show rootBundle; class MyModel need to call loadData as well instead of just reading the already downloaded data  Flutter Stateless widget startup logic. One of the most common scenarios in Mobile development is calling an async function when a new view is shown. In Flutter this can be done using a stateful widget and calling your code in the initState function.

Complete scoped model async call in initstate before widget builds, Complete scoped model async call in initstate before widget builds. 2019-06-18 14:19 ibnhamza imported from Stackoverflow · flutter · scoped-model. I have a  You cannot use BuildContext.inheritFromWidgetOfExactType from this method. However, didChangeDependencies will be called immediately following this method, and BuildContext.inheritFromWidgetOfExactType can be used there. If you override this, make sure your method starts with a call to super.initState ().

MVVM in Flutter using ScopedModel, Implementing the MVVM pattern in Flutter using ScopedModel. By simply calling the utility's notifyListeners() method, in the model, you initiate the initState(); viewModel = MainPageViewModel(api: SwapiService());  lines 15–18 : instantiation of ScopedModel; line 35 : calling the getItems() from the initState to fetch form items;

Comments
  • What do you need a StatefulWidget for when you are using ScopedModel anyways
  • It's a form and need to call setState methods to show whenever selecting values from a modal.
  • if those are async methods try to add them in a separate Future<void> method and await on them, and call this separate method inside initState
  • Thanks for your reply rmtmckenzie. I'll give it a try and let everyone know how it went. Thought scoped model was used as services in angular to make api calls.
  • Yeah in angular there is a scope, but it's quite different than the scoped_model in flutter. In flutter, it's meant as a set of data (model) that happens to be scoped within the widget tree, or at least that's my interpretation of it. Whereas in angular the scope is the binding part between the view and controller.
  • I have taken I think a less complex approach. Since you have to define a model for your initial ScopedModel first, I ended up passing this model as an argument to my managers(using routes atributes of my MaterialApp) and fetch data on the init state for each one of them. This way I maintain my api calls in one place and can fetch data everytime I got into this part of my code. Thanks a lot rmtmckenzie.
  • It's an old question, but recently I found a new way of doing it by using scopedModelDescendant and FutureBuilder widget, which accepts a future as an argument and you can use snapshot in your code to handle different states. Did not know about ScopedModel.Of(context) way of using it I will give it a try to see how it works!
  • @Matias Any chance you could share code example please.
  • I have updated my answer developer9. Sorry for the delay on my response.
  • No worries @Matias. Thanks heaps.