fresh digitable

セミコロンたちが躍動する おいらのコードを 皆さんに 見せたいね

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