Flutter FutureBuilder显示空白屏幕

问题描述 投票:0回答:1

我正在尝试使用未来的构建器在我的应用程序中显示一个cartitems列表。 “等待结果......”显示可能持续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 Widget中添加了一些打印输出:

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在fetch完成之前执行:

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
dart flutter snapshot
1个回答
1
投票

问题可能出在这里:

new ListView(
  children: snapshot.data,
);

参数childrenList<Widget>作为参数。您将数据直接作为参数提供给它,因此它不会在UI上显示任何结果。

您可以使用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;
}

然后返回cartItemscartItems那里取_fetchDocumentData

cartItems = await _fetchDocumentData();

说明:您的循环是异步的,因此在循环执行完成之前返回值。

编辑:正如您在此处所询问的那样,您可能想要进行代码更改。

改变这个:

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;
}
© www.soinside.com 2019 - 2024. All rights reserved.