Skip to content

Instantly share code, notes, and snippets.

@pardom-zz
Created July 4, 2015 00:47
Show Gist options
  • Save pardom-zz/b4157e6e4c512546087d to your computer and use it in GitHub Desktop.
Save pardom-zz/b4157e6e4c512546087d to your computer and use it in GitHub Desktop.
Kotlin observable properties
import com.sun.jdi.InvalidTypeException
import java.util.LinkedHashSet
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
public object Properties {
fun observable<T>(initialValue: T): ReadWriteProperty<Any?, T> {
return ObservableProperty(initialValue)
}
}
public fun Any.getObservers<T>(prop: KProperty<T>): Set<(T) -> Unit> {
return getObservableProperty(prop).observers
}
public fun Any.addObserver<T>(prop: KProperty<T>, observer: (T) -> Unit) {
getObservableProperty(prop).observers.add(observer)
}
public fun Any.addObservers<T>(prop: KProperty<T>, observers: Collection<(T) -> Unit>) {
getObservableProperty(prop).observers.addAll(observers)
}
public fun Any.removeObserver<T>(prop: KProperty<T>, observer: (T) -> Unit) {
getObservableProperty(prop).observers.remove(observer)
}
public fun Any.removeObservers<T>(prop: KProperty<T>, observers: Collection<(T) -> Unit>) {
getObservableProperty(prop).observers.removeAll(observers)
}
public fun Any.retainObservers<T>(prop: KProperty<T>, observers: Collection<(T) -> Unit>) {
getObservableProperty(prop).observers.retainAll(observers)
}
public fun Any.clearObservers<T>(prop: KProperty<T>) {
getObservableProperty(prop).observers.clear()
}
private fun Any.getObservableProperty<T>(prop: KProperty<T>): ObservableProperty<T> {
return try {
getDelegate(prop) as ObservableProperty<T>
} catch(e: ClassCastException) {
throw InvalidTypeException("${prop.name} is of type ObservableProperty")
} catch(e: NoSuchFieldException) {
throw InvalidTypeException("${prop.name} is of type ObservableProperty")
}
}
private fun Any.getDelegate<T>(prop: KProperty<T>): Any {
return javaClass.getDeclaredField("${prop.name}\$delegate").let {
it.setAccessible(true)
it.get(this)
}
}
private class ObservableProperty<T>(initialValue: T) : ReadWriteProperty<Any?, T> {
public val observers: MutableSet<(T) -> Unit> = LinkedHashSet()
private var value = initialValue
public override fun get(thisRef: Any?, desc: PropertyMetadata): T {
return value
}
public override fun set(thisRef: Any?, desc: PropertyMetadata, value: T) {
this.value = value
observers.forEach { it(value) }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment