Как получить данные из запроса firebase на основе значения из другого запроса firebase в FutureBuilder во Flutter?

Я новичок в флаттере, и я уверен, что есть простой способ сделать это. Позвольте мне сначала рассказать вам об истории. У меня есть 2 таблицы (коллекции). Первый хранит сопоставление. Поэтому он возвращает ключ на основе идентификатора, который будет использоваться для запроса второй таблицы и извлечения данных из firebase.

Я написал 2 модели данных и 2 функции, которые возвращают Future<> данные. Они следующие-

Future<SpecificDevice> getSpecificDevice(String deviceId) {
    Future<SpecificDevice> obj =_database.reference().child("deviceMapping").orderByChild("deviceId").equalTo(deviceId).once().then((snapshot) {
      SpecificDevice specificDevice = new SpecificDevice(deviceId, "XXXX", new List<String> ());
      if(snapshot.value.isNotEmpty){
        print(snapshot.value);
        snapshot.value.forEach((key,values) {
          if(values["deviceId"] == deviceId) {
            specificDevice.deviceKey = values["deviceDesc"];
            specificDevice.vendorList = List.from(values["vendorList"]);
          }
        });
      }
      return specificDevice;
    });
    return obj;
  }

Эта функция получает отображение deviceId -> deviceKey. Это ключ записи, хранящийся в другой таблице. Ниже приведена функция для него.

Future<Device> getDeviceDescription(String deviceKey) {
    Future<Device> device = _database.reference().child("deviceDescription").once().then((snapshot) {
      Device deviceObj = new Device("YYYY", "YYYY", "YYY", "YYYY", "YYYY");
      if(snapshot.value.isNotEmpty){
        print(snapshot.value);
        //Future<SpecificDevice> obj = getSpecificDevice(deviceId);
        //obj.then((value) {
          snapshot.value.forEach((key,values) {
            if(key == deviceKey) { // compare with value.deviceKey instead
              print(values["deviceDescription"]); // I get the correct data here.
              deviceObj.manual = values["deviceManual"];
              deviceObj.deviceType = values["deviceType"];
              deviceObj.description = values["deviceDescription"];
              deviceObj.brand = values["deviceBrand"];
              deviceObj.picture = values["devicePicture"];
            }
         // });
        });
      }
      return deviceObj;
    });
    return device;
  }

Теперь обе эти функции работают. Я хочу, чтобы это работало одно за другим. В приведенной выше функции, если я раскомментирую строки кода, данные будут правильно извлечены во внутренней функции, но она вернет начальные значения по умолчанию, поскольку значения возвращаются до установки obj для SpecificDevice.

Вот где я получаю ошибку. Я вызываю вторую функцию в коде FutureBuilder‹> с раскомментированными вышеприведенными строками и принимаю входной параметр как deviceId.

return FutureBuilder<Device>(
              future: getDeviceDescription(deviceId),
              builder:(BuildContext context,AsyncSnapshot snapshot){... // using snapshot.data in its child.

Вот в snapshot.data. дал бы мне YYYY. Но это должно получить мне значение из базы данных. Я застрял с этим на некоторое время. Любая помощь в исправлении этого? или если то, что я пытаюсь сделать, ясно, то, пожалуйста, предложите мне лучший способ приблизиться к этому. Заранее спасибо!


person Leena Bhandari    schedule 31.05.2020    source источник


Ответы (2)


Ответ довольно прост:

  1. в первую очередь — вы забыли использовать ключевые слова async/await, которые будут гарантировать синхронное извлечение данных из БД. Всегда используйте их, если вы подключаетесь к какой-либо сетевой службе

  2. чтобы заставить одну команду работать после другой - используйте .then((value) {}). Он получит данные из первой функции (которую вы передаете с помощью return) и использует их во второй функции.

person Alexey Kunakov    schedule 31.05.2020

Решил проблему, изменив вызывающую функцию на -

return FutureBuilder<Device>(
              future: getSpecificDevice(deviceId).then((value){
                return getDeviceDescription(value.deviceKey);
              }),
              builder:(BuildContext context,AsyncSnapshot snapshot){
person Leena Bhandari    schedule 31.05.2020