Skip to content

Instantly share code, notes, and snippets.

@SecretX33
Last active March 23, 2021 13:14
Show Gist options
  • Save SecretX33/ea78ebf755c6e9984aff234a1f30d586 to your computer and use it in GitHub Desktop.
Save SecretX33/ea78ebf755c6e9984aff234a1f30d586 to your computer and use it in GitHub Desktop.
Listener (without synchronization)
open class Listener<T>(element: T) {
var value: T = element
protected set(value) {
field = value
notifyObservers(field)
}
private val observers: MutableMap<UUID, Observer<T>> = ConcurrentHashMap()
private fun notifyObservers(newValue: T) {
observers.forEach { it.value.onChange(newValue) }
}
fun addListener(observer: Observer<T>): Subscription {
var uuid = UUID.randomUUID()
while(observers.putIfAbsent(uuid, observer) != null) {
Thread.sleep(1)
uuid = UUID.randomUUID()
}
val subscription = Subscription(uuid, this)
return subscription
}
fun unsubscribeListener(uuid: UUID) = observers.remove(uuid)
fun unsubscribeAll() = observers.clear()
}
class MutableListener<T>(element: T) : Listener<T>(element) {
fun set(value: T) { super.value = value }
}
fun interface Observer<T> {
fun onChange(newValue: T)
}
class Subscription(private val uuid: UUID, listener: Listener<*>) {
private var listener: Listener<*>? = listener
fun dispose() {
listener?.unsubscribeListener(uuid)
listener = null
}
}
@SecretX33
Copy link
Author

SecretX33 commented Feb 25, 2021

Listener is read only

val myString = Listener<String>("I am awesome!")
val subscription = myString.addListener(newValue -> println("I am listening for changes: new value is $newValue")

subscription.dispose() // I don't want to listen here anymore

myString.unsubscribeAll() // I don't want anyone listening for changes on this object anymore

//myString.set("No I can't do this...") // Won't compile

If you want to change the value, declare it as or cast it to MutableListener

// creating a new, editable observable object
val editableString = MutableListener("I am editable!")

// from a previous read only listener
val editableString = myString as MutableListener<String>

editableString.set("Hello! I'm a new string")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment