我正在尝试使用未来的构建器在我的应用程序中显示一个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
问题可能出在这里:
new ListView(
children: snapshot.data,
);
参数children
将List<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;
}