Я хочу, чтобы на моем экране отображалось ограниченное количество товаров в GridView
.
Все продукты хранятся в Firebase Firestore, а их изображения — в хранилище Firebase.
Для этого я использую GridView.count
, одним из его параметров является List<Widget> children
. Я хотел сгенерировать список с помощью List.generate
и каждый раз получать продукт из Firestore и его изображение из хранилища, чтобы создать виджет, представляющий продукт.
Проблема в том, что получение продуктов из Firebase является асинхронным, и функция generator
List.generate
не может быть async
. Более того, я возвращаю Future<List<Widget>>
вместо List<Widget>
в параметр children
GridView.count
Любые идеи о том, как это преодолеть?
вот мой код:
GridView.count(
primary: false,
crossAxisCount: 2,
padding: const EdgeInsets.all(20),
crossAxisSpacing: 10,
mainAxisSpacing: 10,
//FIXME: The argument type 'Future<List<Widget>>' can't be assigned to the parameter type 'List<Widget>':
children: _buildGridTileList(15),
)
Future<List<Widget>> _buildGridTileList(int count) async {
var counterCollection = await FirebaseFirestore.instance.collection("Products").doc("Counter").get();
var counterData = counterCollection.data();
return List.generate(
count,
(index) async {
//FIXME: Doesn't work beacuse generator cannot be async!!
var avatarUrl = await FirebaseStorage.instance.ref('${counterData[index]}').child('${counterData[index]}').getDownloadURL();
return Container(
child: Center(
child: NetworkImage(avatarUrl),
),
);
}
);
}
Вы не можете иметь асинхронный код в своей функции сборки, потому что это функция, собирающая дерево виджетов для немедленного рендеринга на экран, вместо этого вы используете виджет StreamBuilder, который дает вам доступ к асинхронным событиям, поток прослушивает будущие данные поступающий из Firebase, и перестраивает этот раздел дерева виджетов при поступлении асинхронного события. вот как это делается, этот код должен быть близок к тому, что вам нужно:
return StreamBuilder(
stream: FirebaseFirestore.instance.collection("Products").snapshots(),
builder:
(BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) {
return Container();
} else {
return GridView.count(
primary: false,
crossAxisCount: 2,
padding: const EdgeInsets.all(20),
crossAxisSpacing: 10,
mainAxisSpacing: 10,
children: List.generate(snapshot.data.docs.length, (index) {
return Image.network(snapshot.data.docs[index].imageUrl);
}),
);
}
});
}