WeakReferenceに包みつつNonNullなプロパティとしてアクセスするためのデリゲートプロパティ
例えばこういうのを
private val _foo= WeakReference<FooActivity>(activity) private val foo: FooActivity get() = requireNotNull(_foo.get())
こんな感じで
private val foo: FooActivity by weakRef(activity)
使えるようにしたい。そんなときはデリゲートプロパティを使って、次のようなものを用意するとよい。
fun <T : Any> weakRef(t: T): ReadOnlyProperty<Any, T> = WeakRefProperty(t) private class WeakRefProperty<T : Any>(t: T) : ReadOnlyProperty<Any, T> { private val _t: WeakReference<T> = WeakReference(t) override fun getValue(thisRef: Any, property: KProperty<*>): T = requireNotNull(_t.get()) }
上の例で、activityじゃなくてそれが持っているViewにアクセスしたいというようなときは、lazyと組み合わせて、
fun <T : Any, R : Any> weakRef( t: T, lazyBlock: (T) -> R ): ReadOnlyProperty<Any, R> = WeakRefPropertyWithLazy(t, lazyBlock) private class WeakRefPropertyWithLazy<R : Any, T : Any>( r: R, lazyBlock: (R) -> T ) : ReadOnlyProperty<Any, T> { val rRef: R by weakRef(r) val tRef: WeakReference<T> by lazy { WeakReference(lazyBlock(rRef)) } override fun getValue(thisRef: Any, property: KProperty<*>): T = requireNotNull(tRef.get()) }
こんな感じのものを用意してやると
private val bar: View by weakRef(activity) { it.findViewById<VIew>(R.id.view_bar) }
このように書ける。NavControllerとかを取得するのもよい。
UdonRoad2/WeakRefProperty.kt at master · akihito104/UdonRoad2 · GitHub