Reputation: 61
Can you please help me? I need to load data from cloud firestore into a List<> and I need that before flutter runs the build() method. The idea is to have this list ready to use its values from a StreamBuilder. In the next image I explain what I want to solve:
VISUAL WIDGET: https://i.sstatic.net/fv0eg.jpg
Right now I request the Brands from Cloud Firestore using Futures, it works but I use an async method so when I have the List ready the Widget has rendered already and I can't search in List because is empty by the time StreamBuilder resolves. I know that I could request the data of a specific brand from the builder of the StreamBuilder BUT I think there's a better way to do it because the brand collecion won't change and I had to request the Brand Data in every StreamBuilder event, it could work but I don't feel so good about that solution. So if I could get a List at the beginig I can save many requests to get the brand data from cloud firestore.
CODE WIDGET:
class _GeneralInventoryPageState extends State<GeneralInventoryPage> {
ServiceFirestore _serviceFirestore = new ServiceFirestore();
static final _appResources = new AppResources();
Stream<QuerySnapshot> _streamGenericProducts; // STREAM OF PRODUCTS OF CLOUD FIRESTORE
List<MapMarca> _allBrands; // THIS IS THE LIST I WANT TO FILL WITH BRANDS OF CLOUD FIRESTORE
@override
void initState() {
super.initState();
final productCollectionName = _appResources.getResource("productCollectionName");
_streamGenericProducts = _serviceFirestore.serviceGetCollection(productCollectionName); // initialize Stream
_allBrands = new List<MapMarca>(); //initialize List<brand>
_getAllBrands();
}
void _getAllBrands() async {
var marcasRaw = await _serviceFirestore.serviceGetUniqueDocumentByCollectionName(collectionName, documentId);
if(marcasRaw == null){
print("Error");
}
else{
ModelMarca marcas = ModelMarca.fromMap(Map<String, dynamic>.from(marcasRaw)); //decoding brands
this._allBrands = marcas.listBrand; // set the List<brand>
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Inventario')
),
body: Container(
child: StreamBuilder(
stream: this._streamGenericProducts,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
return CircularProgressIndicator();
}
else {
List<ModelProduct> genericProductList = [];
QuerySnapshot querySnapshot = snapshot.data;
querySnapshot.documents.forEach((doc){
final genericProduct = ModelProduct.fromMap(Map<String,dynamic>.from(doc.data));
genericProduct.strIdRecord = doc.documentID;
genericProductList.add(genericProduct);
});
return createProductListView(context, genericProductList);
}
},
)
),
);
}
//I use createProductListView to Create every product section detail (this method is not important)
Widget createProductListView(BuildContext context, List<ModelProduct> genericProductList) {
return ListView(
children: List<Widget>.from(genericProductList.map((genericProducto)=>createProductListTile(context,genericProducto)).toList())
);
}
// Here I build every single Product Detail, I simplify the code, please look how I get the Brand Name
Widget createProductListTile(BuildContext context, ModelProduct genericProduct) {
return Column(
children: <Widget>[
ListTile(
title: Column(
children: <Widget>[
Row(
children: <Widget>[
Container(
//code for getting the product image
),
]
),
// some code about product info....
Row(
children: <Widget>[
Expanded(child: Text("Marca: ${_getBrandName(brandCode: genericProduct.strProductBrand)}")) //HERE I ALWAYS GET "NO BRAND INFO "
],
),
// some code about product info...
],
),
),
],
);
}
String _getBrandName({String brandCode}) {
MapMarca marca = _searchBrand(brandId: brandCode);
if(marca == null) {
return "NO BRAND INFO"; // this is what is get when I run my app in the Brand Field
}
else {
return marca.valor;
}
}
}
Upvotes: 3
Views: 6010
Reputation: 997
try to load your data in didchangeDependenices:-
@override
void didChangeDependencies() {
super.didChangeDependencies();
//try to load all your data in this method :)
}
Upvotes: 0
Reputation: 399
Try using a FutureBuilder
FutureBuilder(
future: *Your Data to Load*,
builder: (BuildContext context, AsyncSnapshot snapshot) {
return *Your Widgets*;
})
Upvotes: 4