0

I am working on a project using Flutter with scoped_model as state manager.

But there is one point that I'm not sure to understand. I'm actually calling my API at every single build which looks weird to me. What is the good practice to make API calls using state management as scoped_model ? Here is my actual widget's code :

class RunsListPage extends StatelessWidget {
  final ScopedRuns scopedRuns = ScopedRuns();

  @override
  Widget build(BuildContext context) {
    this.scopedRuns.getRuns();
    return ScopedModel<ScopedRuns>(
        model: this.scopedRuns,
        child: ScopedModelDescendant<ScopedRuns>(
          builder: (context, child, scopedRuns) {
            return Column(
              children: <Widget>[
                Expanded(
                  child: Stack(
                    children: <Widget>[
                      LoadingIndicatorWidget(
                        visible: scopedRuns.isLoading,
                      ),
                      RefreshIndicator(
                        color: Theme.of(context).primaryColor,
                        onRefresh: () async => this.scopedRuns.getRuns(),
                        child: RunsList(
                            runsList: scopedRuns.runs ?? [],
                            visible: !scopedRuns.isLoading),
                      ),
                    ],
                  ),
                )
              ],
            );
          },
        ));
  }}

and here is my getRuns() method from my ScopedRuns model :

  getRuns() async {
    _isLoading = true;
    notifyListeners();
    _runs = await APIService.getRuns();
    _isLoading = false;
    notifyListeners();
  }
Q. Eude
  • 841
  • 11
  • 24

2 Answers2

0

The build method should be pure and without side effects. So you can either : 1. Call the getRuns method during the initiation of your ScopedRuns class

class ScopedRuns {
  ScopedRuns(){
    getRuns();
  }
}

2. Convert RunsListPage into a statfeul widget and call the method during initState

class RunsListPage extends StatefulWidget {
  @override
  _RunsListPageState createState() => _RunsListPageState();
}

class _RunsListPageState extends State<RunsListPage> {
  final ScopedRuns scopedRuns = ScopedRuns();

  @override
  void initState() {
    super.initState();
    scopedRuns.getRuns();
  }

  @override
  Widget build(BuildContext context) { ... }
Raouf Rahiche
  • 28,948
  • 10
  • 85
  • 77
0

notice that any methods call you made inside your build may gets called multiple times when the app needs to build which is quite a lot you should put your method in initState(); so it will gets called only once.