Попытка реализовать загрузку счетчика при загрузке данных из Firestore с Flutter - PullRequest
0 голосов
/ 09 января 2020

Я работаю над приложением, которое отображает счетчик при загрузке данных из 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. Я просто пропустил важный код? Или я использовал неправильный метод?

Проблема заключалась в том, что страница заказов показала 0 данных, хотя список в _fetchOrdersData () имеет 1 элемент.

для полного исходного кода здесь, на github

Ответы [ 3 ]

1 голос
/ 09 января 2020

Остальные ответы выглядят разумно. Им просто не хватает проверок данных, которые я считаю необходимыми во всех моих приложениях. Потому что, если у меня хорошее соединение, а hasData - true, а hasError - false, то, возможно, документов вообще не будет. Это должно быть проверено. Вот фрагмент из моих проектов.

Проверка состояния подключения аналогична проверке snapshot.hasError.

Widget _getMyFriends() {
return StreamBuilder<QuerySnapshot>(
  stream: Database.getFriendsByUserId(widget.loggedInUserId),
  builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
    if (snapshot.hasError)
      return Center(child: Text("Error"));
    else if (!snapshot.hasData)
      return Center(child: Text("Loading..."));
    else if (snapshot.data.documents.isEmpty) //also check if empty! show loader?
      return Center(child: Text("No friends added yet."));
    else
      return ListView(
        children: snapshot.data.documents.map((DocumentSnapshot document) {
          return SimpleUserPanel(userId: document['friendid']);
        }).toList(),
      );
  }
);

}

0 голосов
/ 09 января 2020

Обращаясь к своему коду, вы должны проверить на ConnectionState.active также с вашим snapshot.connectionState == ConnectionState.waiting.

На самом деле у вас больше мощности и контроля при использовании FutureBuilder или StreamBuilder. Ниже приведен пример кода:

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();
  }
0 голосов
/ 09 января 2020

Вы должны сделать следующее:

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 блок.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...