使用Flutter从Firestore加载数据时尝试实现加载微调器

时间:2020-01-08 22:33:33

标签: firebase flutter google-cloud-firestore

我正在开发一个在后端从Firestore加载数据时显示微调器的应用程序,但它没有按预期工作,并且我正努力寻找缺陷。

我的订单页面代码

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:table_service/providers/order.dart';

import '../providers/session.dart';

class OrdersPage extends StatefulWidget {
  bool isLoading = true;

  @override
  _OrdersPageState createState() => _OrdersPageState();
}

class _OrdersPageState extends State<OrdersPage> {
  List<Order> _orders = [];
  @override
  Widget build(BuildContext context) {
    final session = Provider.of<Session>(context, listen: false);

    return Scaffold(
      floatingActionButton: session.privilege == 'Administrator' ||
              session.privilege == 'Waiter' ||
              session.privilege == 'Customer'
          ? FloatingActionButton(
              heroTag: 'OrdersPageFAB',
              onPressed: () {},
              child: Icon(Icons.add, color: Colors.white),
            )
          : null,
      body: FutureBuilder(
        future: session.fetchOrdersData(),
        builder: (ctx, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return Center(child: CircularProgressIndicator());
          } else {
            print(snapshot.data);
            return GridView.builder(
              gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                crossAxisCount: 2,
                childAspectRatio: 2 / 2,
              ),
              itemCount: _orders.length,
              itemBuilder: (_, i) {
                return Padding(
                  padding: const EdgeInsets.all(5.0),
                  child: Card(
                    child: GridTile(
                      child: Icon(
                        Icons.library_books,
                        size: 100.0,
                        color: Colors.grey,
                      ),
                      footer: GridTileBar(
                        backgroundColor: Colors.black54,
                        title: Text('Order by: ${_orders[i].name}'),
                      ),
                    ),
                  ),
                );
              },
            );
          }
        },
      ),
    );
  }
}

fetchOrdersData()处理程序

final Auth auth = Auth();
final Firestore database = Firestore.instance;

String user_name;
String privilege;

List<Food> _foods = [];
List<Order> _orders = [];
List<TransactionModel.Transaction> _transactions = [];

... 
...

Future fetchOrdersData() async  {
  _orders.clear();
  return await  database.collection('orders').getDocuments().then((documents) {
    documents.documents.forEach((order) {
      database
          .collection('users')
          .document(order.data['uid'])
          .get()
          .then((user) {
        _orders.add(Order(
          id: order.documentID,
          tableNumber: order.data['tablenumber'],
          orderDate: (order.data['orderdate'] as Timestamp).toDate(),
          status: order.data['status'],
          note: order.data['note'],
          uid: order.data['uid'],
          name: user.data['user_name'],
        ));
      });
    });
    return _orders;
  });
  notifyListeners();
}

get getOrders {
  return [..._orders];
}

我尝试了许多方法,包括StreamBuilder,setState()和最近的FutureBuilder。 我只是错过了重要的密码吗? 还是我使用了错误的方法?

问题是即使_fetchOrdersData()上的列表具有1个元素,订单页面仍显示0个数据。

获取完整的源代码 here on github

3 个答案:

答案 0 :(得分:2)

其他答案看起来很合理。他们只是缺少数据验证检查,我发现所有我的应用程序都需要这些检查。因为如果我拥有良好的连接,并且hasData为true且hasError为false,则可能根本没有文档。应该检查一下。这是我的项目的一部分。

检查连接状态与检查快照.hasError相同。

setTimeouts

}

答案 1 :(得分:0)

您应该执行以下操作:

else {
         if(snapshot.hasData){
            print(snapshot.data);
            return GridView.builder(
              gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                crossAxisCount: 2,
                childAspectRatio: 2 / 2,
              ),
              itemCount: _orders.length,
              itemBuilder: (_, i) {
                return Padding(
                  padding: const EdgeInsets.all(5.0),
                  child: Card(
                    child: GridTile(
                      child: Icon(
                        Icons.library_books,
                        size: 100.0,
                        color: Colors.grey,
                      ),
                      footer: GridTileBar(
                        backgroundColor: Colors.black54,
                        title: Text('Order by: ${_orders[i].name}'),
                      ),
                    ),
                  ),
                );
              },
        // By default, show a loading spinner.
         return CircularProgressIndicator();
           },

因此,首先使用属性snapshot检查hasData是否具有数据,由于这是异步的,它将首先执行return CircularProgressIndicator();,然后执行if块。

答案 2 :(得分:0)

看看您的代码,您还必须用ConnectionState.active检查snapshot.connectionState == ConnectionState.waiting

实际上,使用FutureBuilderStreamBuilder时,您具有更多的功能和控制力。下面是一个示例代码片段:

switch (snapshot.connectionState) {
    case ConnectionState.none:
      return Center(child: Text("Check Connection"));
    case ConnectionState.active:
    case ConnectionState.waiting:
      return Center(child: CircularProgressIndicator(backgroundColor: Theme.of(context).primaryColorLight,));
    case ConnectionState.done:
      if (snapshot.hasError) {
        return Center(child: Text("Error occured!"));
      } else if (snapshot.hasData) {
        return YourWidgetWithData();
      } else {
        debugPrint("What went wrong");
        return SizedBox();
      }
      break;
    default:
      return SizedBox();
  }