SJoshi
SJoshi

Reputation: 1976

How to abstract away hardware with RXJava and Observables without Subjects?

I'm working on a project where I have a hardware device talking to my Android app over a USB cable. Protocol buffers, wrapped in a thin serialization layer is my communication protocol.

Currently, the USB communication happens using an asynchronous listener which monitors the USB. From here, I read the bytes that came from my hardware, act on them (e.g. deserialize them, unwrap the protobuf, etc...), and set whatever member variables and such appropriately.

My public API to this class + service is 2 Observables:

Observable<DeviceInfo> getDeviceInfoObservable() 
Observable<DeviceState> getDeviceStateObservable()

Here's the trick: Filling the DeviceInfo requires 5 back and forth async calls (not my design), and the DeviceState will keep being sent up from the hardware as long as the app is open.

For the device info, I wait until all 5 are ready, and then I notify my observers (I know I can do subscriber-side filtering, but I would rather push a fully-ready DeviceInfo), for the state, I just push those as I receive them.

My question: Is there a way to do this WITHOUT using Subjects as backing stores for the DeviceInfo and DeviceState? I keep reading about how evil Subjects are, and while I don't believe they are evil (however, they're not necessarily 'functional'), this seems like a good use with an external IO that I can't control.

mSerial.addReadListener(size -> {
  byte[] data = mSerial.read(size);
  // extract data into something usable
  ...
  if (mDeviceInfo.isReady()) {
    mInfoSubject.onNext(mDeviceInfo);
  }
  ...
  mSubject.onNext(mDeviceState);
}

Upvotes: 0

Views: 364

Answers (1)

krp
krp

Reputation: 2247

You can wrap your listener around Observable, like this :

Observable.create(subscriber -> mSerial.addReadListener(
        size -> {
            byte[] read = mSerial.read(size);
            subscriber.onNext(read);

            subscriber.add(Subscriptions.create(() -> {
                // Remove listener
            }));
        }));

then you can map this Observable and get whatever device info you need from byte array.

Upvotes: 1

Related Questions