Most "Kotlin-esque" way to implement a "live" collection of objects that represent devices?

I am writing code that is able to scan for devices. As soon as they show up, a collection is automatically populated. (I do not mean “collection” specifically as in “Kotlin standard collection classes”. I am referring to a collection as a design concept.) I start a scan, and as soon as a device is found, an object is added to the collection, and this object represents the newly found device. If the device goes away, then it is automatically removed from the collection. If other pieces of code accessed the collection and got a reference to such an object, then the object remains usable, but in a “zombie” state, where all IO calls fail. (This fixes a race condition when a device goes away while some other coroutine or thread is using the object.)

I now wonder how to do this in the most Kotlin-esque way. I want to use coroutines.

One way would be a SharedFlow that is associated with the collection and which announces that object X was added or removed. So, something like SharedFlow<Pair<DeviceObject, Boolean>> where the boolean is true if the associated object was added and false if it was removed. (In production code, this would be a dedicated class instead of a Pair, and an enum class instead of the boolean.) But perhaps there are better ways to do this? Or does something in the standard library or in a mature third party library exist for such “live” collections?

SharedFlow is good, though it should probably contain a List of Pairs/classes.

1 Like

What about a StateFlow<Set<DeviceObject>>?
A listenable state containing the currently connected devices is conceptually sound, instead of sending single connect-disconnect events.

2 Likes

The only concern I have about that is that it may be wasteful if the set becomes very large. Otherwise I like the idea.

I guess that depends on the use case. If you’re making a user application where the user has <10 devices that are connected/disconnected once or twice a minute, then thinking about the performance of the set is premature optimization.
If you’re making a backend application where there are thousands of devices that are connected/disconnected every 100ms, then maybe the performance of the set is not good enough and you may want to use an event bus instead (sharedflow with single connect/disconnect) and manage the state elsewhere.
Depends on your use case.

The event bus solution you propose seems fine to me. I’d personally use a custom data class instead of the Pair, and maybe even an enum instead of boolean, just for semantics, but personal preference.

1 Like