Created
July 4, 2015 00:47
-
-
Save pardom-zz/b4157e6e4c512546087d to your computer and use it in GitHub Desktop.
Kotlin observable properties
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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