FLUTTER: Как загрузить данные перед методом build () - PullRequest
0 голосов
/ 14 июля 2020

Не могли бы вы мне помочь? Мне нужно загрузить данные из облачного хранилища в List <>, и мне это нужно до того, как flutter запустит метод build (). Идея состоит в том, чтобы этот список был готов к использованию значений из StreamBuilder. На следующем изображении я объясняю, что хочу решить:

ВИЗУАЛЬНЫЙ ВИДЖЕТ: https://i.stack.imgur.com/fv0eg.jpg

Прямо сейчас я запрашиваю бренды из Cloud Firestore с использованием Futures, это работает но я использую метод asyn c, поэтому, когда у меня есть готовый список, виджет уже отрисован, и я не могу выполнять поиск в списке, поскольку он пуст к моменту разрешения StreamBuilder. Я знаю, что могу запросить данные определенного c бренда у создателя StreamBuilder, НО я думаю, что есть лучший способ сделать это, потому что набор брендов не изменится, и мне пришлось запрашивать данные бренда в каждом StreamBuilder. событие, это может сработать, но я не очень доволен этим решением. Так что, если бы я мог получить список с самого начала, я мог бы сохранить много запросов на получение данных о бренде из облачного хранилища.

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

Ответы [ 2 ]

2 голосов
/ 14 июля 2020

Попробуйте использовать FutureBuilder

FutureBuilder(
    future: *Your Data to Load*,
    builder: (BuildContext context, AsyncSnapshot snapshot) {
      return *Your Widgets*;
 })
0 голосов
/ 14 июля 2020

попробуйте загрузить ваши данные в didchangeDependenices: -

 @override
 void didChangeDependencies() {
  super.didChangeDependencies();
 
 //try to load all your data in this method :)

 }
...