web-dev-qa-db-fra.com

Flutter - Future builder: quand dois-je l'utiliser

Je me demandais quand utiliser le futur constructeur. Par exemple, si je veux faire une requête http et afficher les résultats dans une vue de liste, dès que vous ouvrez la vue, dois-je utiliser le futur générateur ou simplement construire un ListViewBuilder comme:

new ListView.builder(
        itemCount: _features.length,
        itemBuilder: (BuildContext context, int position) {
...stuff here...
}

De plus, si je ne veux pas construire une vue de liste mais des choses plus complexes comme des graphiques circulaires, devrais-je avoir à utiliser le futur constructeur?

J'espère que c'est assez clair!

15
Little Monkey

FutureBuildersupprime certains des codes passe-partout.

Disons que vous voulez fetch data from backend Au lancement de la page et montrer le chargeur jusqu'à ce que les données arrivent.

Tâches pour ListBuilder:

  • ont deux variables d'état 1 .dataFromBackend 2 .isLoadingFlag
  • Au lancement, définissez isLoadingFlag = true Et en fonction de quel spectacle loader.
  • Une fois les données arrivées, définissez les données avec ce que vous obtenez de backend et définissez isLoadingFlag = false (Dans setState évidemment)
  • Nous devons avoir un if-else Dans la création de widget. Si isLoadingFlag est true, affichez loader sinon affichez data. En cas d'échec, affichez error message.

Tâches pour FutureBuilder:

  • donner la tâche asynchrone dans future de Future Builder
  • basé sur connectionState, afficher message (loading, active(streams), done)
  • basé sur data(snapshot.hasError) afficher la vue

Avantages de FutureBuilder

  • pas de two flags et pas de setState
  • programmation réactive (FutureBuilder se chargera de mettre à jour la vue à l'arrivée des données)

Exemple:

    new FutureBuilder<String>(
        future: _fetchNetworkCall, // async work
        builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
           switch (snapshot.connectionState) {
             case ConnectionState.waiting: return new Text('Loading....');
             default:
               if (snapshot.hasError)
                  return new Text('Error: ${snapshot.error}');
               else
              return new Text('Result: ${snapshot.data}');
            }
         },
        )

Impact sur les performances:

Je viens de regarder dans le code FutureBuilder pour comprendre l'impact performance de l'utilisation de ceci.

  • FutureBuilder est juste un StatefulWidget dont la variable state est _snapshot
  • L'état initial est _snapshot = new AsyncSnapshot<T>.withData(ConnectionState.none, widget.initialData);
  • Il s'abonne à future que nous envoyons dans le constructeur et met à jour le state en fonction de cela.

    widget.future.then<void>((T data) {
        if (_activeCallbackIdentity == callbackIdentity) {
      setState(() {
        _snapshot = new AsyncSnapshot<T>.withData(ConnectionState.done, data);
       });
     }
    }, onError: (Object error) {
    if (_activeCallbackIdentity == callbackIdentity) {
      setState(() {
        _snapshot = new AsyncSnapshot<T>.withError(ConnectionState.done, error);
      });
     }
    });
    

Ainsi, le FutureBuilder est un wrapper/passe-partout de ce que nous faisons généralement. Il ne devrait donc pas y avoir d'impact sur les performances.

30