首页 > 解决方案 > 自动从firestore获取数据后如何启动状态

问题描述

我是颤振的初学者,我在我的应用程序的历史页面上工作,我想做的是从 Firestore 获取数据,然后处理该数据并将其存储到一个列表中,这样我就可以在 dashbord 小部件中构建我的历史项目,问题是除非我手动刷新状态,否则项目不会出现,在我的情况下,我使用这个过滤器图标,获取我数据的函数是 getVente(),我在 initState() 中调用它,我希望这个函数在我加载页面的那一刻执行,所以项目也是如此,而不是手动执行。这是发生了什么图片gif

这是代码

import 'package:flutter/material.dart';
import 'package:rflutter_alert/rflutter_alert.dart';
import 'package:chips_choice/chips_choice.dart';
import 'package:stocknsell/Components/DownSelect.dart';
import 'package:stocknsell/Components/DownSelect2.dart';
import 'package:date_range_picker/date_range_picker.dart' as DateRagePicker;
import 'package:stocknsell/Components/historyitem.dart';

final Color backgroundColor = Color(0xFF4A4A58);

class HistoriquePage extends StatefulWidget {
  static String id = "/history";
  @override
  _HistoriquePageState createState() => _HistoriquePageState();
}

class _HistoriquePageState extends State<HistoriquePage>
    with SingleTickerProviderStateMixin {
  bool isCollapsed = true;
  double screenWidth, screenHeight;
  final Duration duration = const Duration(milliseconds: 300);
  AnimationController _controller;
  Animation<double> _scaleAnimation;
  Animation<double> _menuScaleAnimation;
  Animation<Offset> _slideAnimation;
  Vente vente;
  List<Vente> list = List();
  List<Produit> produits = List();
  Produit produit = Produit();

  @override
  void initState() {
    getVente();
    _controller = AnimationController(vsync: this, duration: duration);
    _scaleAnimation = Tween<double>(begin: 1, end: 0.8).animate(_controller);
    _menuScaleAnimation =
        Tween<double>(begin: 0.5, end: 1).animate(_controller);
    _slideAnimation = Tween<Offset>(begin: Offset(-1, 0), end: Offset(0, 0))
        .animate(_controller);
    super.initState();
  }

  void getVente() async {
    bool trouve = false;
    await for (var snapshots
        in FirebaseFirestore.instance.collection('vente').snapshots()) {
      for (var ventes in snapshots.docs) {
        if ((ventes['client_id'] != null) && (ventes['date'] != null)) {
          if (list.isNotEmpty) {
            for (var sells in list) {
              if ((sells.clientid == ventes['client_id']) &&
                  (sells.date == ventes['date'])) {
                trouve = true;
                produit = Produit();
                produit.baseprice = ventes['baseprice'];
                produit.couttotale = ventes['couttotale'];
                produit.nbarticle = ventes['nb_product'];
                produit.prixpromo = ventes['prixpromo'];
                produit.nom = ventes['marque'];
                sells.produits.add(produit);
                sells.montant += produit.couttotale;
              }
            }
            if (!trouve) {
              vente = Vente(
                clientid: ventes['client_id'],
                clientnom: ventes['client_name'],
                date: ventes['date'],
                data: ventes,
                montant: ventes['couttotale'],
              );
              produit = Produit();
              produit.baseprice = ventes['baseprice'];
              produit.couttotale = ventes['couttotale'];
              produit.nbarticle = ventes['nb_product'];
              produit.prixpromo = ventes['prixpromo'];
              produit.nom = ventes['marque'];
              vente.produits = List<Produit>();
              vente.produits.add(produit);
              list.add(vente);
            }
            trouve = false;
          } else {
            vente = Vente(
              clientid: ventes['client_id'],
              clientnom: ventes['client_name'],
              date: ventes['date'],
              data: ventes,
              montant: ventes['couttotale'],
            );
            vente.produits = List<Produit>();
            produit = Produit();
            produit.baseprice = ventes['baseprice'];
            produit.couttotale = ventes['couttotale'];
            produit.nbarticle = ventes['nb_product'];
            produit.prixpromo = ventes['prixpromo'];
            produit.nom = ventes['marque'];
            vente.produits.add(produit);
            list.add(vente);
          }
        }
      }
    }
    setState(() {});
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    Size size = MediaQuery.of(context).size;
    screenHeight = size.height;
    screenWidth = size.width;
    return Scaffold(
      backgroundColor: backgroundColor,
      body: Stack(
        children: <Widget>[
          menu(context),
          dashboard(context),
        ],
      ),
    );
  }

  int tag = 0;
  List<String> options = [
    'Date',
    'Client',
    'Montant',
  ];
  final elements1 = [
    "Alger",
    "Harach",
    "Beo",
    "Said Hamdine",
    "Ain Naadja",
    "Kouba",
    "Garidi",
  ];

  _openPopup(context) {
    DateTime mindate, maxdate;
    Alert(
        context: context,
        title: "Filtres",
        style: AlertStyle(
            backgroundColor: Colors.grey[200],
            titleStyle: TextStyle(
                fontFamily: 'Mom cake',
                fontWeight: FontWeight.bold,
                fontSize: 34)),
        content: SizedBox(
          width: screenWidth,
          height: screenHeight * 0.6,
          child: Padding(
            padding: const EdgeInsets.only(left: 8.0),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: <Widget>[
                Text("Trier par :",
                    style: TextStyle(
                        fontFamily: 'Mom cake',
                        fontWeight: FontWeight.bold,
                        fontSize: 34)),
                Row(
                  children: [
                    Expanded(
                      child: ChipsChoice<int>.single(
                        value: tag,
                        onChanged: (val) => setState(() => tag = val),
                        choiceItems: C2Choice.listFrom<int, String>(
                          source: options,
                          value: (i, v) => i,
                          label: (i, v) => v,
                        ),
                        choiceStyle: C2ChoiceStyle(
                          color: Colors.black,
                          borderRadius:
                              const BorderRadius.all(Radius.circular(10)),
                        ),
                      ),
                    ),
                  ],
                ),
                Text("Secteur :"),
                MyStatefulWidget(),
                Text("Client : "),
                MyStatefulWidget2(),
                Text("Montant de vente"),
                Row(
                  children: [
                    SizedBox(
                      width: 110.0,
                      child: TextFormField(
                        decoration: InputDecoration(
                          labelText: 'MIN',
                          border: OutlineInputBorder(),
                        ),
                      ),
                    ),
                    SizedBox(
                      width: 8,
                      child: Divider(
                        thickness: 2.0,
                      ),
                    ),
                    SizedBox(
                      width: 110.0,
                      child: TextFormField(
                        decoration: InputDecoration(
                          labelText: 'MAX',
                          border: OutlineInputBorder(),
                        ),
                      ),
                    ),
                  ],
                ),
                Text("Date de vente"),
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    SizedBox(
                      width: 150.0,
                      height: 70,
                      child: IconButton(
                        icon: Icon(
                          Icons.date_range_rounded,
                        ),
                        onPressed: () async {
                          final List<DateTime> picked =
                              await DateRagePicker.showDatePicker(
                                  context: context,
                                  initialFirstDate: new DateTime.now(),
                                  initialLastDate: new DateTime.now()
                                      .add(new Duration(days: 7)),
                                  firstDate: new DateTime(2015),
                                  lastDate: new DateTime(2030));
                          if (picked != null && picked.length == 2) {
                            mindate = picked[1];
                            maxdate = picked[2];
                          }
                        },
                      ),
                    ),
                  ],
                ),
              ],
            ),
          ),
        ),
        buttons: [
          DialogButton(
            onPressed: () => Navigator.pop(context),
            child: Text(
              "Filtrer",
              style: TextStyle(color: Colors.white, fontSize: 17),
            ),
          ),
          DialogButton(
            onPressed: () => Navigator.pop(context),
            child: Text(
              "Réinitialiser",
              style: TextStyle(color: Colors.white, fontSize: 17),
            ),
          )
        ]).show();
  }

  Widget menu(context) {
    return ... some widget ...
  }

  Widget dashboard(context) {
    return AnimatedPositioned(
      duration: duration,
      top: 0,
      bottom: 0,
      left: isCollapsed ? 0 : 0.6 * screenWidth,
      right: isCollapsed ? 0 : -0.2 * screenWidth,
      child: ScaleTransition(
        scale: _scaleAnimation,
        child: Material(
          animationDuration: duration,
          borderRadius: BorderRadius.all(Radius.circular(40)),
          elevation: 8,
          color: backgroundColor,
          child: SingleChildScrollView(
            scrollDirection: Axis.vertical,
            physics: ClampingScrollPhysics(),
            child: Container(
              padding: const EdgeInsets.only(left: 16, right: 16, top: 37),
              child: SingleChildScrollView(
                scrollDirection: Axis.vertical,
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: <Widget>[
                    Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      mainAxisSize: MainAxisSize.max,
                      children: [
                        InkWell(
                          child: Icon(Icons.menu, color: Colors.white),
                          onTap: () {
                            setState(() {
                              if (isCollapsed) {
                                _controller.forward();
                              } else
                                _controller.reverse();

                              isCollapsed = !isCollapsed;
                            });
                          },
                        ),
                        Text("Historique",
                            style:
                                TextStyle(fontSize: 24, color: Colors.white)),
                        IconButton(
                            icon: CircleAvatar(
                              radius: 15.0,
                              backgroundImage:
                                  AssetImage('assets/images/search.png'),
                            ),
                            onPressed: () {
                              _openPopup(context);
                              setState(() {});
                            })
                      ],
                    ),
                    ListView.builder(
                      scrollDirection: Axis.vertical,
                      shrinkWrap: true,
                      itemCount: list.length,
                      itemBuilder: (context, index) {
                        return HistoryItem(
                          client_id: list[index].clientid,
                          date: list[index].date,
                          clientnom: list[index].clientnom,
                          screenWidth: MediaQuery.of(context).size.width,
                          documentSnapshot: list[index].data,
                          montant: list[index].montant,
                          produits: list[index].produits,
                        );
                      },
                    ),
                  ],
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

class Vente {
  DocumentSnapshot data;
  String clientid;
  String clientnom;
  String date;
  double montant;
  List<Produit> produits;
  Vente(
      {@required this.clientid,
      this.date,
      this.data,
      this.clientnom,
      this.produits,
      this.montant});
}

class Produit {
  String nom;
  int baseprice;
  double prixpromo;
  double couttotale;
  int nbarticle;
  Produit(
      {this.baseprice,
      this.nbarticle,
      this.nom,
      this.couttotale,
      this.prixpromo});
}

标签: firebaseflutterdartgoogle-cloud-firestore

解决方案


您可以使用FutureBuilder小部件。用FutureBuilder包装您的ListView.builder

FutureBuilder<List<Vente>(
  future: getVente(),
  builder: (context, stream){
    if(stream.hasData){
       return ListView.builder();
    } else {
       return CircularProgressIndicator() ;
    }
  }

)

更新您的 getVente() 方法

Future<List<Vente>> getVente() async {
  bool trouve = false;
  await for (QuerySnapshot snapshots
      in FirebaseFirestore.instance.collection('vente').snapshots()) {
    for (var ventes in snapshots.docs) {
      if ((ventes['client_id'] != null) && (ventes['date'] != null)) {
        if (list.isNotEmpty) {
          for (var sells in list) {
            if ((sells.clientid == ventes['client_id']) &&
                (sells.date == ventes['date'])) {
              trouve = true;
              produit = Produit();
              produit.baseprice = ventes['baseprice'];
              produit.couttotale = ventes['couttotale'];
              produit.nbarticle = ventes['nb_product'];
              produit.prixpromo = ventes['prixpromo'];
              produit.nom = ventes['marque'];
              sells.produits.add(produit);
              sells.montant += produit.couttotale;
            }
          }
          if (!trouve) {
            vente = Vente(
              clientid: ventes['client_id'],
              clientnom: ventes['client_name'],
              date: ventes['date'],
              data: ventes,
              montant: ventes['couttotale'],
            );
            produit = Produit();
            produit.baseprice = ventes['baseprice'];
            produit.couttotale = ventes['couttotale'];
            produit.nbarticle = ventes['nb_product'];
            produit.prixpromo = ventes['prixpromo'];
            produit.nom = ventes['marque'];
            vente.produits = List<Produit>();
            vente.produits.add(produit);
            list.add(vente);
          }
          trouve = false;
        } else {
          vente = Vente(
            clientid: ventes['client_id'],
            clientnom: ventes['client_name'],
            date: ventes['date'],
            data: ventes,
            montant: ventes['couttotale'],
          );
          vente.produits = List<Produit>();
          produit = Produit();
          produit.baseprice = ventes['baseprice'];
          produit.couttotale = ventes['couttotale'];
          produit.nbarticle = ventes['nb_product'];
          produit.prixpromo = ventes['prixpromo'];
          produit.nom = ventes['marque'];
          vente.produits.add(produit);
          list.add(vente);
        }
      }
    }
  }
  return list; // Add this here
}


解释

FutureBuilder<T>将等待未来完成。

在这种情况下,FutureBuilder<void>什么都没有,所以你的方法getVente()返回 void。它将等到代码完成,并通知构建器。在这种情况下,您不需要调用getVente()initState 中的方法,因为 FutureBuilder 会为您完成。

您也可以选择FutureBuilder<List<Vente>>哪个更好,但是您需要对代码进行相当多的更改。它需要一个 Vente 对象列表,您可以在构建器方法中使用它。

future.connectionState == ConnectionState.waiting将检查未来是否仍在连接中,并且尚未完成。在这种情况下,构建器将显示一个CircularProgressIndicator(),

当 future 完成时,它将返回 ListView.builder 方法。

如果需要,您可以找到有关FutureBuilder的更多信息。

如果您希望在值更改时更新小部件,也可以使用StreamBuilder 。

StreamBuilder<List<Vente>(
  stream: getVente(),
  builder: (context, future){
    if(future.hasData){
       return ListView.builder();
    } else {
       return CircularProgressIndicator() ;
    }
  }

)

更新您的 getVente() 方法

Stream<List<Vente>> getVente() async* {
  bool trouve = false;
  await for (QuerySnapshot snapshots
      in FirebaseFirestore.instance.collection('vente').snapshots()) {
    for (var ventes in snapshots.docs) {
      if ((ventes['client_id'] != null) && (ventes['date'] != null)) {
        if (list.isNotEmpty) {
          for (var sells in list) {
            if ((sells.clientid == ventes['client_id']) &&
                (sells.date == ventes['date'])) {
              trouve = true;
              produit = Produit();
              produit.baseprice = ventes['baseprice'];
              produit.couttotale = ventes['couttotale'];
              produit.nbarticle = ventes['nb_product'];
              produit.prixpromo = ventes['prixpromo'];
              produit.nom = ventes['marque'];
              sells.produits.add(produit);
              sells.montant += produit.couttotale;
            }
          }
          if (!trouve) {
            vente = Vente(
              clientid: ventes['client_id'],
              clientnom: ventes['client_name'],
              date: ventes['date'],
              data: ventes,
              montant: ventes['couttotale'],
            );
            produit = Produit();
            produit.baseprice = ventes['baseprice'];
            produit.couttotale = ventes['couttotale'];
            produit.nbarticle = ventes['nb_product'];
            produit.prixpromo = ventes['prixpromo'];
            produit.nom = ventes['marque'];
            vente.produits = List<Produit>();
            vente.produits.add(produit);
            list.add(vente);
          }
          trouve = false;
        } else {
          vente = Vente(
            clientid: ventes['client_id'],
            clientnom: ventes['client_name'],
            date: ventes['date'],
            data: ventes,
            montant: ventes['couttotale'],
          );
          vente.produits = List<Produit>();
          produit = Produit();
          produit.baseprice = ventes['baseprice'];
          produit.couttotale = ventes['couttotale'];
          produit.nbarticle = ventes['nb_product'];
          produit.prixpromo = ventes['prixpromo'];
          produit.nom = ventes['marque'];
          vente.produits.add(produit);
          list.add(vente);
        }
      }
    }
  }
  yield list; // Add this here
}

推荐阅读