1

Any RxJava experts that can help me figure this one out? I have a function that returns a Single<ByteArray> based on some position parameter. Basically, I want to keep calling that function, until it returns an empty ByteArray.

NOTE: The position parameter is supposed to indicate how many bytes where already read. E.g. first time it will be 0, next time it will be how many bytes where retrieved the first time, and so on.

This is what I have now:

fun readBytes(position: Int) : Single<ByteArray>{ ... }


fun readAllLogs() : Single<LogEntry> {

    val oldPosition = AtomicInteger(0)
    val position = AtomicInteger(0)
    Observable.defer {
        readBytes(position.get())
    }.reduceWith({ LogEntry() }, { log, bytes -> 
        position.addAndGet(bytes.size)
        log += bytes
        log
    }).repeatUntil { 

        val canWeStop = position.get() == oldPosition.get()
        oldPosition.set(position.get())
        canWeStop

    }.toObservable()
}

For completeness, here's my LogEntry accumulator

data class LogEntry {
    var data: ByteArray = byteArrayOf()
        private set


    operator fun plusAssign(bytes: ByteArray) {
        data += bytes
    }
}

Question 1: How can I exit this stream elegantly? E.g. not keeping track of separate variables outside the stream?

Question 2: Any optimizations I can make? I'm going from Single to Observable twice to be able to chain these operators. I'm sure that can be more efficient

Entreco
  • 12,738
  • 8
  • 75
  • 95
  • To keep track of those variables outside of the stream in a clean way you wrap the content of readAllLogs with Observable.defer. That way the returned Observable will be well-behaved in that it can be subscribed to many times without side-effects arising from the state of those variables. – Dave Moten Oct 27 '21 at 10:34

0 Answers0