How to map a stream that depends on another stream to a new model depending on both streams?

Issue

I have 2 Firestore streams where the 2nd one depends on the 1st one. I want to emit new models that depend on data from both streams.

In pseudocode you can think of it in a following way:

// 1st stream emits some device data
final streamA = client.device(id: 0); // Stream<DeviceData>

// 2nd stream emits some metadata for the above device type
final streamB = client.deviceMetadata(type: device.type); // Stream<DeviceMetadata>

// and finally I want to receive stream of combined device (device data + metadata)
final combinedObject = Device.from(deviceData, deviceMetadata);

However, I cannot find an effective way of mapping a stream onto another stream while accessing the value from the source stream. For instance with .map() I would like to write:

return client.device('deviceId')
   .map((device) => client.deviceMetadata(type: device.type))
   .map((deviceMetadata) => Device.from(???, deviceMetadata));

The problem is of course that I don’t know how to access device in the second map().

What stream transformation or rxdart extension I could use to achieve that?

Solution

Ok, after some tweaking I think I’ve found a solution

// get the initial stream
final deviceStream = client.device(id: id);

// create new stream depending on the first one
final deviceTypeStream = deviceStream.flatMap( // make sure to flatten the stream so that it's not Stream<Stream<..>>
  (device) => client.deviceMetadata(type: device.type),
);

// use withLatestFrom to capture the latest value from the deviceTypeStream
// and create desired object out of that

return deviceTypeStream.withLatestFrom<DeviceData, Device>(
  deviceStream,
  (deviceType, device) => Device(device, deviceType),
);

Answered By – Dominik Roszkowski

Answer Checked By – Terry (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *