Flutter FutureBuilder显示空白屏幕

时间:2019-04-13 10:04:22

标签: dart flutter snapshot

我正在尝试与未来的构建者一起在我的应用中显示列表项。显示“正在等待结果...”大约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 个答案:

答案 0 :(得分: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;
}

并且在返回cartItems之前,先从cartItems提取_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;
}