Flutter FutureBuilder показывает пустой экран - PullRequest
0 голосов
/ 13 апреля 2019

Я пытаюсь отобразить список картем в моем приложении с будущим компоновщиком.«Ожидание результата ...» отображается, возможно, в течение 0,5 с, а затем отображается только белый экран.Когда я заменяю Listview на текст, текст отображается так, как задумано.Так что это как-то связано со снимком, я думаю ...

 Widget buildList()  {
return new FutureBuilder<List<CartItem>> (
    future:  getCartItems(),
builder: (context, snapshot) {

 switch (snapshot.connectionState) {
   case ConnectionState.none:
     return new Text('Press button to start');
   case ConnectionState.waiting:
     return new Text('Awaiting result...');
   default:

     print(snapshot.data);
     print(snapshot.hasData);

     return
       (!snapshot.hasData)

           ?
       new Container(
           alignment: FractionalOffset.center,
           child: new CircularProgressIndicator())
           :
       new ListView(
         children: snapshot.data,
       );
 }});
}}

Это мой getCartItems :

Future<List<CartItem>> getCartItems() async {
final FirebaseUser user = await FirebaseAuth.instance.currentUser();

final uid = user.uid;
List<CartItem> cartItems = [];

QuerySnapshot data = await Firestore.instance
    .collection("carts")
    .where('owner', isEqualTo: uid)
    .where('active', isEqualTo: true)
    .getDocuments();

data.documents.forEach((DocumentSnapshot doc) async {
  var keys =  doc["products"].keys.toList();
  var values =  doc["products"].values.toList();

   for (var i = 0; i < keys.length; i++){
     await Firestore.instance.collection('products').document(keys[i]).get().then((DocumentSnapshot ds) {
      cartItems.add( new CartItem.fromDocument(ds, values[i]));
      print(cartItems);

     });
  }
});
return cartItems;
 }

Я знаю, что Futurebuilder называетсядважды: https://github.com/flutter/flutter/issues/18490

Но я не знаю, как справиться с этой ситуацией ...

Есть идеи?Действительно ли мне нужен FutureBuilder в этом сценарии?

РЕДАКТИРОВАТЬ:

Я добавил несколько отпечатков в виджет buildList со следующим выводом:

Performing hot reload...
Reloaded 5 of 710 libraries in 808ms.
I/flutter (23685): []           <--- snapshit.data
I/flutter (23685): true         <--- snapshot.hasData

РЕДАКТИРОВАТЬ 2:

Изменения, но все еще не работают:

    Future<List<CartItem>> getCartItems() async {
   final FirebaseUser user = await FirebaseAuth.instance.currentUser();

   final uid = user.uid;
   List<CartItem> cartItems = [];

   QuerySnapshot data = await Firestore.instance
       .collection("carts")
       .where('owner', isEqualTo: uid)
       .where('active', isEqualTo: true)
       .getDocuments();

   cartItems = await _fetchDocumentData(data);
   return cartItems;
 }

 Future<List<CartItem>> _fetchDocumentData(data) async {
 List<CartItem> cartItems = [];
 data.documents.forEach((DocumentSnapshot doc) {
 var keys =  doc["products"].keys.toList();
 var values =  doc["products"].values.toList();
 for (var i = 0; i < keys.length; i++){
  Firestore.instance.collection('products').document(keys[i]).get().then((DocumentSnapshot ds) {
 cartItems.add( new CartItem.fromDocument(ds, values[i]));
 print(cartItems);
 });
 }
 });
 return cartItems;
}

РЕДАКТИРОВАТЬ 3:

Выход вконсоль выглядит так, как будто Futurebuilder выполняется до завершения выборки:

I/flutter ( 4535): []          <--- print(snapshot.data) in FutureBuilder
I/flutter ( 4535): true        <--- print(snapshot.hasData) in FutureBuilder
I/flutter ( 4535): [CartItem]  <--- print(cartItems) in _fetchDocumentData

1 Ответ

1 голос
/ 13 апреля 2019

Проблема может быть здесь:

new ListView(
  children: snapshot.data,
);

Параметр children принимает List<Widget> в качестве параметра. Вы предоставляете данные непосредственно ему в качестве параметра, поэтому он не показывает никаких результатов для пользовательского интерфейса.

Вы можете использовать ListView.builder для отображения ваших данных следующим образом:

ListView.builder(
    itemCount: snapshot.data.length,
    itemBuilder: (context, position) {
        var cartItem = snapshot.data[position];
        return Row(
            children: <Widget>[
                Expanded(child: Text(cartItem.id)), // just for example
                Expanded(child: Text(cartItem.name)), // just for example
                Expanded(child: Text(cartItem.color)), // just for example
            ],
        );
    },
)

Изменить: поместите код для извлечения данных в метод, подобный _fetchDocumentData, и объявите этот метод async и получите тип возврата Future<List<CartItem>>, подобный этому:

Future<List<CartItem>> _fetchDocumentData async {    
   List<CartItem> cartItems = [];    
   data.documents.forEach((DocumentSnapshot doc) {
     var keys =  doc["products"].keys.toList();
     var values =  doc["products"].values.toList();

     for (var i = 0; i < keys.length; i++){
        await Firestore.instance.collection('products').document(keys[i]).get().then((DocumentSnapshot ds) {
         cartItems.add( new CartItem.fromDocument(ds, values[i]));
         print(cartItems);    
       });
    }
  });    
 return cartItems;
}

и перед возвратом cartItems извлекать cartItems из _fetchDocumentData вот так

cartItems = await _fetchDocumentData();

Explaination: Ваш цикл асинхронный, поэтому значения возвращаются до завершения выполнения цикла.

Редактировать: Как вы спросили здесь, изменения кода, которые вы, возможно, захотите внести.

Изменить это:

Future<List<CartItem>> getCartItems() async {
  final FirebaseUser user = await FirebaseAuth.instance.currentUser();

  final uid = user.uid;
  List<CartItem> cartItems = [];

  QuerySnapshot data = await Firestore.instance
      .collection("carts")
      .where('owner', isEqualTo: uid)
      .where('active', isEqualTo: true)
      .getDocuments();

  data.documents.forEach((DocumentSnapshot doc) async {
    var keys =  doc["products"].keys.toList();
    var values =  doc["products"].values.toList();
    for (var i = 0; i < keys.length; i++){
       await Firestore.instance.collection('products').document(keys[i]).get().then((DocumentSnapshot ds) {
        cartItems.add( new CartItem.fromDocument(ds, values[i]));
        print(cartItems);
       });
    }
  });
  return cartItems;
 }

К этому:

Future<List<CartItem>> getCartItems() async {
final FirebaseUser user = await FirebaseAuth.instance.currentUser();

final uid = user.uid;
List<CartItem> cartItems = [];

QuerySnapshot data = await Firestore.instance
    .collection("carts")
    .where('owner', isEqualTo: uid)
    .where('active', isEqualTo: true)
    .getDocuments();

cartItems = await _fetchDocumentData();
return cartItems;
 }

Future<List<CartItem>> _fetchDocumentData async {
    List<CartItem> cartItems = [];
    data.documents.forEach((DocumentSnapshot doc) {
      var keys =  doc["products"].keys.toList();
      var values =  doc["products"].values.toList();
      for (var i = 0; i < keys.length; i++){
        await Firestore.instance.collection('products').document(keys[i]).get().then((DocumentSnapshot ds) {
          cartItems.add( new CartItem.fromDocument(ds, values[i]));
          print(cartItems);
        });
      }
    });
  return cartItems;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...