Quel est le FutureBuilder dans Flutter

Future Builder est un widget qui se construit tout seul. Mais, cela nécessite un instantané de l’interaction avec un Future.

Comment allons-nous obtenir Future?

Nous devons avoir obtenu Future. de trois manières.

Il s’agit de State.initState, State.didUpdateWidget ou State.didChangeDependencies.

Qu’est-ce que ça veut dire?

Nous pouvons avoir obtenu le Futur soit par changement d’état, soit par changement de dépendances.

Cela signifie beaucoup.

Pourquoi?

La raison en est que nous pouvons utiliser FutureBuilder en utilisant Scoped Model ou Provider. En d’autres termes, en utilisant le Inherited Widget.

En fait, nous allons faire la même chose ici.

Nous utiliserons à la fois Scoped Model et Provider pour insérer des données dans une SQLite database. En conséquence, le widget FutureBuilder se reconstruira et récupérera les données.

En fait, nous allons exécuter des fonctions asynchrones. Par conséquent, la fonction asynchrone fera la mise à jour de User Interface ou UI.

Par défaut, FutureBuilder est de nature avec stateful. Il maintient son propre state.

Comment fonctionne FutureBuilder ?

Le FutureBuilder affiche des messages tels que « chargement ». Il le fait en fonction de l’état de la connexion. Et, après cela, en fonction de nouvelles « données » ou « instantanés », il met à jour l’interface utilisateur ou UI. En conséquence, nous obtenons une nouvelle vue.

L’avantage de FutureBuilder est qu’il n’utilise pas deux « variables d’état ». Lorsque les nouvelles « données » arrivent, il met à jour la « vue ».

Pour résumer, le FutureBuilder est un wrapper ou un passe-partout de ce que nous faisons.

Quelle est la différence entre FutureBuilder et StreamBuilder ?

Nous discuterons de la classe StreamBuilder dans un article séparé. Cependant, la classe StreamBuilder présente certaines similitudes avec la classe FutureBuilder.

Premièrement, ils écoutent les changements qui se produisent sur leurs objets respectifs.

Deuxièmement, après cela, ils déclenchent une nouvelle construction lorsqu’ils reçoivent la notification.

C’est la fonctionnalité de base qu’ils pratiquent tous les deux.

Alors, quelle est la différence ?

L’objet fait la différence. C’est l’objet qu’ils écoutent.

Comme nous l’avons dit précédemment, #Future est une représentation d’une fonction asynchrone. Du coup, le #Future n’a qu’une seule et unique réponse.

Si le #Future est terminé avec succès, nous obtenons le résultat. Sinon, nous obtenons l’erreur.

D’autre part, le #Stream obtiendra chaque nouvelle valeur. Même s’il y avait une erreur, nous obtiendrions la dernière valeur.

Par conséquent, la principale différence est qu’un #Future ne peut pas écouter un changement qui varie. Le #Future a toujours une seule réponse.

Assez parlé.

Voyons d’abord les captures d’écran. La visualisation des images de nos applications Flutter clarifiera le concept.

Après cela, nous discuterons du code respectif.

Quand dois-je utiliser FutureBuilder ?

Dans notre première application Flutter, nous allons utiliser le modèle de portée et le fournisseur avec un seul widget FutureBuilder. En conséquence, il ne fonctionne pas correctement.

Cependant, les données ont été correctement insérées dans la base de données SQLite.

Dans un premier temps, nous allons essayer d’insérer des données dans une base de données SQLite par un objet Provider.

Par conséquent, au départ, notre application Flutter ressemblera à ce qui suit.

Future Builder example one

Future Builder example one

Appuyons sur le bouton. Selon notre code, il doit insérer deux objets User. L’un du fournisseur et l’autre de la classe Scoped Model.

Étant donné que FutureBuilder écoute les deux objets, il doit mettre à jour l’interface utilisateur et afficher deux noms d’utilisateur.

Mais cela ne s’est pas produit.

Future Builder example two with Scoped Mode and Provider

Future Builder example two with Scoped Mode and Provider

Le nom du deuxième utilisateur ne s’affichera que lorsque nous cliquerons sur le bouton ci-dessous.

Future Builder example two

Future Builder example two

Si nous cliquons à nouveau sur le bouton « Ajouter des utilisateurs par fournisseur », un seul nom est affiché sous les deux utilisateurs. Bien que le deuxième utilisateur soit inséré, il ne se reflète pas sur l’interface utilisateur.

Vérifions le code où nous avons mélangé le Scoped Model et le Provider.

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

import 'package:scoped_model/scoped_model.dart';

import '/model/user_model.dart';
import '/model/user_prvider.dart';
import '/model/database_handler.dart';
import '/model/user.dart';

class MyHomePage extends StatelessWidget {
  const MyHomePage({Key? key}) : super(key: key);

  static const String title = 'Provider, Scoped Model, SQLite';

  @override
  Widget build(BuildContext context) {
    final userModel = ScopedModel.of<UserModel>(context);
    final userProvider = Provider.of<UserProvider>(context);

    final handler = DatabaseHandler();
    Future<int> addUsers() async {
      User firstUser = User(
        name: userModel.userOne.name,
        location: userModel.userOne.location,
      );
      User secondUser = User(
        name: userProvider.userTwo.name,
        location: userProvider.userTwo.location,
      );
      List<User> listOfUsers = [
        firstUser,
        secondUser,
      ];
      return await handler.insertUser(listOfUsers);
    }

    return ScopedModelDescendant<UserModel>(
      builder: (context, child, model) => Scaffold(
        appBar: customAppBar(title),
        body: FutureBuilder(
          future: handler.retrieveUsers(),
          builder: (BuildContext context, AsyncSnapshot<List<User>> snapshot) {
            if (snapshot.hasData) {
              return ListView.builder(
                itemCount: snapshot.data?.length,
                itemBuilder: (BuildContext context, int index) {
                  return Column(
                    children: [
                      Card(
                        child: ListTile(
                          key: ValueKey<int>(snapshot.data![index].id!),
                          contentPadding: const EdgeInsets.all(8.0),
                          title: Text(
                            snapshot.data![index].name,
                            style: const TextStyle(
                              fontSize: 30,
                              color: Colors.red,
                            ),
                          ),
                          subtitle: Text(
                            snapshot.data![index].location,
                            style: const TextStyle(
                              fontSize: 20,
                              color: Colors.blue,
                            ),
                          ),
                        ),
                        elevation: 20,
                      ),
                      TextButton(
                        onPressed: () {
                          handler.initializeDB().whenComplete(() async {
                            await addUsers();
                          });
                          model.addingUsers();
                        },
                        child: const Text(
                          'Add Users by Scoped Model',
                          style: TextStyle(
                            fontSize: 20,
                            fontWeight: FontWeight.w600,
                          ),
                        ),
                      )
                    ],
                  );
                },
              );
            } else {
              return const Center(child: CircularProgressIndicator());
            }
          },
        ),
        floatingActionButton: FloatingActionButton.extended(
          onPressed: () {
            handler.initializeDB().whenComplete(() async {
              await addUsers();
            });
            userProvider.addingUsers();
          },
          label: const Text(
            'Add Users by Provider',
            style: TextStyle(
              fontSize: 25,
              fontWeight: FontWeight.bold,
            ),
          ),
        ),
      ),
    );
  }

  AppBar customAppBar(String title) {
    return AppBar(
      centerTitle: true,
      //backgroundColor: Colors.grey[400],
      flexibleSpace: Container(
        decoration: const BoxDecoration(
          gradient: LinearGradient(
            colors: [
              Colors.pink,
              Colors.grey,
            ],
            begin: Alignment.topRight,
            end: Alignment.bottomRight,
          ),
        ),
      ),
      elevation: 20,
      titleSpacing: 80,
      title: Text(
        title,
        textAlign: TextAlign.left,
      ),
    );
  }
}

Pour le code complet, veuillez visiter le référentiel GitHub respectif.

Cependant, nous aurions pu les séparer. Et c’est ce que nous avons fait pour la deuxième application Flutter.

En conséquence, FutureBuilder et notre application Flutter fonctionnent parfaitement.

Comment réinitialiser le futur constructeur Flutter ?

Cette fois, nous allons ajouter le premier utilisateur en utilisant le modèle Scoped.

Future Builder example three

Future Builder example three

Si nous appuyons sur le bouton ci-dessous, l’utilisateur sera ajouté et le nom et l’emplacement de l’utilisateur seront également affichés. De plus, sous l’affichage de l’objet User nouvellement créé, nous pouvons voir le « Bouton de navigation ».

Future Builder example four

Future Builder example four

Voyons d’abord le code. Après cela, nous cliquerons sur le bouton « Page suivante » pour ajouter un autre utilisateur par le fournisseur.

Premièrement, nous voyons la classe User Model qui étend la classe Model à partir de la dépendance Scoped Model.

import 'package:scoped_model/scoped_model.dart';

import 'user.dart';

class UserModel extends Model {
  User _userModel = User(name: 'John Smith', location: 'Back East');
  User get userModel => _userModel;

  void addingUsers() {
    _userModel = userModel;

    notifyListeners();
  }
}

Deuxièmement, nous verrons le widget FutureBuilder qui utilise le modèle d’utilisateur à portée dépendante pour ajouter les utilisateurs.

import 'package:flutter/material.dart';

import 'package:scoped_model/scoped_model.dart';

import '/model/user_model.dart';

import '/model/database_handler.dart';
import '/model/user.dart';
import 'provider_home_page.dart';

class ModelHomePage extends StatelessWidget {
  const ModelHomePage({Key? key}) : super(key: key);

  static const String title = 'Adding by Scoped Model';

  @override
  Widget build(BuildContext context) {
    final userModel = ScopedModel.of<UserModel>(context);

    final handler = DatabaseHandler();
    Future<int> addUsers() async {
      User firstUser = User(
        name: userModel.userModel.name,
        location: userModel.userModel.location,
      );

      List<User> listOfUsers = [
        firstUser,
      ];
      return await handler.insertUser(listOfUsers);
    }

    return ScopedModelDescendant<UserModel>(
      builder: (context, child, model) => Scaffold(
        appBar: customAppBar(title),
        body: FutureBuilder(
          future: handler.retrieveUsers(),
          builder: (BuildContext context, AsyncSnapshot<List<User>> snapshot) {
            if (snapshot.hasData) {
              return ListView.builder(
                itemCount: snapshot.data?.length,
                itemBuilder: (BuildContext context, int index) {
                  return Column(
                    children: [
                      Card(
                        child: ListTile(
                          key: ValueKey<int>(snapshot.data![index].id!),
                          contentPadding: const EdgeInsets.all(8.0),
                          title: Text(
                            snapshot.data![index].name,
                            style: const TextStyle(
                              fontSize: 30,
                              color: Colors.red,
                            ),
                          ),
                          subtitle: Text(
                            snapshot.data![index].location,
                            style: const TextStyle(
                              fontSize: 20,
                              color: Colors.blue,
                            ),
                          ),
                        ),
                        elevation: 20,
                      ),
                      TextButton(
                        onPressed: () {
                          Navigator.push(
                            context,
                            MaterialPageRoute(
                              builder: (context) => const ProviderHomePage(),
                            ),
                          );
                        },
                        child: const Text(
                          'Next Page, Add by Provider',
                          style: TextStyle(
                            fontSize: 20,
                            fontWeight: FontWeight.w600,
                          ),
                        ),
                      )
                    ],
                  );
                },
              );
            } else {
              return const Center(child: CircularProgressIndicator());
            }
          },
        ),
        floatingActionButton: FloatingActionButton.extended(
          onPressed: () {
            handler.initializeDB().whenComplete(() async {
              await addUsers();
            });
            userModel.addingUsers();
          },
          label: const Text(
            'Add Users by Model',
            style: TextStyle(
              fontSize: 25,
              fontWeight: FontWeight.bold,
            ),
          ),
        ),
      ),
    );
  }

  AppBar customAppBar(String title) {
    return AppBar(
      centerTitle: true,
      //backgroundColor: Colors.grey[400],
      flexibleSpace: Container(
        decoration: const BoxDecoration(
          gradient: LinearGradient(
            colors: [
              Colors.pink,
              Colors.grey,
            ],
            begin: Alignment.topRight,
            end: Alignment.bottomRight,
          ),
        ),
      ),
      elevation: 20,
      titleSpacing: 80,
      title: Text(
        title,
        textAlign: TextAlign.left,
      ),
    );
  }
}

Ensuite, nous allons à la page suivante où nous pouvons ajouter le deuxième utilisateur en utilisant le fournisseur.

Future Builder example five

Future Builder example five

La page suivante montre correctement qu’un utilisateur a déjà été ajouté à la base de données SQLite.

Maintenant, lorsque nous ajoutons le bouton « Ajouter des utilisateurs par fournisseur », un autre utilisateur est ajouté. De plus, deux utilisateurs s’affichent correctement sur l’interface utilisateur.

Future Builder example six

Future Builder example six

Voyons maintenant le code.

Tout d’abord, nous examinerons la classe User Provider qui étend le ChangeNotifier. Après cela, il en informe les auditeurs.

import 'package:flutter/material.dart';

import 'user.dart';

class UserProvider with ChangeNotifier {
  User _userProvider = User(name: 'Json Web', location: 'Detroit');
  User get userProvider => _userProvider;

  void addingUsers() {
    _userProvider = userProvider;

    notifyListeners();
  }
}

Deuxièmement, nous verrons le FutureBuilder qui se reconstruit lorsque l’objet User change d’état.

Nous avons créé un autre FutureBuilder pour cette page, afin que nous puissions ajouter des utilisateurs par fournisseur.

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

import '/model/user_prvider.dart';
import '/model/database_handler.dart';
import '/model/user.dart';

class ProviderHomePage extends StatelessWidget {
  const ProviderHomePage({Key? key}) : super(key: key);

  static const String title = 'Adding By Provider';

  @override
  Widget build(BuildContext context) {
    final userProvider = Provider.of<UserProvider>(context);

    final handler = DatabaseHandler();
    Future<int> addUsers() async {
      User secondUser = User(
        name: userProvider.userProvider.name,
        location: userProvider.userProvider.location,
      );
      List<User> listOfUsers = [
        secondUser,
      ];
      return await handler.insertUser(listOfUsers);
    }

    return Scaffold(
      appBar: AppBar(
        title: const Text(title),
      ),
      body: FutureBuilder(
        future: handler.retrieveUsers(),
        builder: (BuildContext context, AsyncSnapshot<List<User>> snapshot) {
          if (snapshot.hasData) {
            return ListView.builder(
              itemCount: snapshot.data?.length,
              itemBuilder: (BuildContext context, int index) {
                return Column(
                  children: [
                    Card(
                      child: ListTile(
                        key: ValueKey<int>(snapshot.data![index].id!),
                        contentPadding: const EdgeInsets.all(8.0),
                        title: Text(
                          snapshot.data![index].name,
                          style: const TextStyle(
                            fontSize: 30,
                            color: Colors.red,
                          ),
                        ),
                        subtitle: Text(
                          snapshot.data![index].location,
                          style: const TextStyle(
                            fontSize: 20,
                            color: Colors.blue,
                          ),
                        ),
                      ),
                      elevation: 20,
                    ),
                  ],
                );
              },
            );
          } else {
            return const Center(child: CircularProgressIndicator());
          }
        },
      ),
      floatingActionButton: FloatingActionButton.extended(
        onPressed: () {
          handler.initializeDB().whenComplete(() async {
            await addUsers();
          });
          userProvider.addingUsers();
        },
        label: const Text(
          'Add Users by Provider',
          style: TextStyle(
            fontSize: 25,
            fontWeight: FontWeight.bold,
          ),
        ),
      ),
    );
  }
}

Dans la deuxième application Flutter, nous avons utilisé avec succès le modèle Scoped et le fournisseur. Cependant, nous avons implémenté le widget FutureBuilder séparément.

Pour l’extrait de code complet de cette application Flutter, veuillez visiter le référentiel GitHub respectif.

Et ensuite ?

Books at Leanpub

Books in Apress

My books at Amazon

Courses at Educative

GitHub repository

Technical blog

Twitter

Comments

3 responses to “Quel est le FutureBuilder dans Flutter”

  1. […] l’idée centrale derrière l’utilisation de widgets est de construire notre interface utilisateur à l’aide de […]

  2. […] faire une animation de héros en flutter […]

  3. […] l’idée centrale derrière l’utilisation de widgets est de construire notre interface utilisateur à l’aide de […]

Leave a Reply