dart - 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
解决方案
问题可能在这里:
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
fetch之前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;
}
推荐阅读
- javascript - 使用实时 Firebase 的 If-else 条件
- pandas - 使用 pandas 在 PostgreSQL 中将 ndarray 存储为 blob
- javascript - 样式未应用于所有 hbs 文件
- java - 如何使用 JFrame 与 API 建立连接
- javascript - 如何从字符串中获取数字以在角度/打字稿中一起计算它们?
- laravel - Auth::user()->通知在 laravel 实时服务器中不起作用
- java - 如何将图像路径文件获取到一个活动到另一个活动
- javascript - 单击数组中的每个元素并提取信息
- python - kivy-ios:安装 grpc ==> FileNotFoundError:[Errno 2] 没有这样的文件或目录:'/bin/false
- laravel - 基于通用模型的 CRUD API Laravel