首页 > 解决方案 > Flutter FutureBuilder 显示黑屏

问题描述

我正在尝试使用未来的构建器在我的应用程序中显示一个 caritems 列表。“等待结果...”可能会显示 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

标签: dartfluttersnapshot

解决方案


问题可能在这里:

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;
}

在像这样返回cartItemsfetch之前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;
}

推荐阅读