Skip to content

Instantly share code, notes, and snippets.

@xingstarx
Forked from pardom-zz/Properties.kt
Last active January 15, 2018 10:31
Show Gist options
  • Save xingstarx/ccba100649b46bf25407a498bbe18a33 to your computer and use it in GitHub Desktop.
Save xingstarx/ccba100649b46bf25407a498bbe18a33 to your computer and use it in GitHub Desktop.
Kotlin observable properties
/**
** 为KProperty0添加一个扩展函数addObserver(),用来监听当值发生变化的时候刷新observer代码块
**/
fun <T> KProperty0<T>.addObserver(observer: (T) -> Unit) {
(getDelegate(this) as ObservableProperty<T>?)?.addObserver(observer)
}
private fun <T> getDelegate(kProperty: KProperty0<T>) : Any? {
val owner = (kProperty as PropertyReference).owner
val containerClass: Class<*>
try {
containerClass = (owner!!::class.members as ArrayList).firstOrNull { it.name == "jClass" }?.call(owner) as Class<*>
} catch (e: Exception) {
throw IllegalArgumentException("No such property 'jClass'")
}
containerClass.declaredFields.firstOrNull { it.name == kProperty.name + "\$delegate" }?.let { field ->
field.isAccessible = true
// try {
// val modifyFiled = field.javaClass.getDeclaredField("modifiers")
// modifyFiled.isAccessible = true
// modifyFiled.setInt(field, modifyFiled.getInt(field) and Modifier.FINAL.inv())
// } catch (e: NoSuchFieldException) {
// e.printStackTrace()
// }
return field.get(kProperty.boundReceiver)
}
return null
}
open class ObservableProperty<T>(v: T) : ReadWriteProperty<Any?, T> {
val observers: MutableSet<(T) -> Unit> = LinkedHashSet()
private var value: T = v
override fun getValue(thisRef: Any?, property: KProperty<*>): T {
return value
}
override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
this.value = value
observers.forEach { it(value) }
}
fun addObserver(observer: (T) -> Unit) {
observers.add(observer)
}
}
@xingstarx
Copy link
Author

原来的这段代码用的是

fun <T> KProperty0<T>.addObserver(observer: (T) -> Unit) {
    (apply { isAccessible = true }.getDelegate() as MutableProperty<T>).addObserver(observer)
}

发现不稳定,会存在报错的情况,所以用java反射的方式来获取delegate对象

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