Search code examples
firebaseflutterdartfirebase-realtime-databasedatamodel

How to get data from firebase query based on value from another firebase query in FutureBuilder in Flutter?


I am new to flutter and I am sure there is a simple way of doing this. Let me first give you a background. I have 2 tables(collections). The first one store a mapping. Therefore it returns a key based on an id which will be used to query the second table and retrieve the data from firebase.

I have written 2 data models and 2 functions which return Future<> data. They are as follows-

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

This function gets the mapping deviceId -> deviceKey. This is the key of record stored in another table. Following is the function for it.

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

Now both of these functions work. I want to make it work one after the other. In the above function, if I uncomment the lines of code, the data is retrieved properly in the inner function but it returns initial default values set because the values get returned before setting the obj of SpecificDevice.

Here is where I am getting the error. I am calling the second function in FutureBuilder<> code with the above lines uncommented and taking input param as deviceId.

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

Here in snapshot.data. would give me YYYY. But it should get me the value from the database. I am stuck with this for a while. Any help in fixing this? or if what I am trying to do is clear then please suggest me a better way to approach this. Thanks in advance!


Solution

  • Solved the problem by changing the calling function to -

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