Is there a better way to do this? ```class FlowDel...
# codereview
m
Is there a better way to do this?
Copy code
class FlowDelegate<T>: ReadWriteProperty<Any, Flow<T>> {
    private val deferredFlow = CompletableDeferred<Flow<T>>()

    override fun setValue(thisRef: Any, property: KProperty<*>, value: Flow<T>) {
        deferredFlow.complete(value)
    }

    override fun getValue(thisRef: Any, property: KProperty<*>): Flow<T> {
        return if (deferredFlow.isCompleted) {
            deferredFlow.getCompleted()
        } else {
            flow {
                emitAll(deferredFlow.await())
            }
        }
    }
}

/** Usage */
class MySample {
    private var _sampleFlow by FlowDelegate<String>()

    val sampleFlow: Flow<String>
        get() = _sampleFlow

    fun init(args: ...) {
        _sampleFlow = flow<String> { /* based on args */ }
    }
}
z
I would think you would want to throw if you try setting the property more than once, since that isn't supported.
m
Good point, thanks! I was expecting something like this in the coroutines library, because it seems like a quite common use case.
z
I don’t know your actual use case, but using
Deferred<Flow<>>
directly for this seems more clear/less magical, and isn’t really that much boilerplate.
m
But then won’t you need a suspend function to access the flow object?
z
No, you could do the same trick you are where you wrap it in a flow. Can't remember if there's a Deferred.asFlow function but you could chain that with flatten to get the same thing.
m
Maybe something like this instead (this time allowing init() to be called multiple times)?
Copy code
class MySample {
    private val _sampleFlowChannel = ConflatedBroadcastChannel<Flow<String>>()

    val sampleFlow: Flow<String>
        get() = _sampleFlowChannel.asFlow().flattenConcat()

    fun init(args: ...) {
        val f = flow<String> { /* based on args */ }
        _sampleFlowChannel.offer(f)
    }
}
👍 1
m
why flow {emitAll … and not flowOf(deferredFlow.await) ?
m
@myanmarking Because that requires a suspend function.
m
yes, right
on the other hand, i think it’s safe to say emitAll should be emit. right ? Actually, i’m not sure now 😛