作者热门文章
- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
所以我使用 kotlin
for android,并且在膨胀 View 时,我倾向于执行以下操作:
private val recyclerView by lazy { find<RecyclerView>(R.id.recyclerView) }
这种方法会奏效。但是,在某些情况下,它会导致应用程序出错。如果这是一个fragment,并且fragment进入backstack,onCreateView
会被再次调用,并且fragment的 View 层次将被重新创建。这意味着,惰性启动的 recyclerView 将指出一个不再存在的旧 View 。
解决办法是这样的:
private lateinit var recyclerView: RecyclerView
并初始化onCreateView
里面的所有属性。
我的问题是,有没有办法重置惰性属性,以便它们可以再次初始化?我喜欢初始化都在类的顶部完成的事实,这有助于保持代码的组织性。具体问题在这个问题中找到:kotlin android fragment empty recycler view after back
最佳答案
这是一个可重置懒惰的快速版本,它可能更优雅并且需要仔细检查线程安全,但这基本上是这个想法。您需要一些东西来管理(跟踪)惰性代表,以便您可以调用重置,然后是可以管理和重置的东西。这将 lazy()
包装在这些管理类中。
以下是您的 final类的样子,例如:
class Something {
val lazyMgr = resettableManager()
val prop1: String by resettableLazy(lazyMgr) { ... }
val prop2: String by resettableLazy(lazyMgr) { ... }
val prop3: String by resettableLazy(lazyMgr) { ... }
}
然后让懒惰的人在下次访问时都回到新值:
lazyMgr.reset() // prop1, prop2, and prop3 all will do new lazy values on next access
resettablelazy的实现:
class ResettableLazyManager {
// we synchronize to make sure the timing of a reset() call and new inits do not collide
val managedDelegates = LinkedList<Resettable>()
fun register(managed: Resettable) {
synchronized (managedDelegates) {
managedDelegates.add(managed)
}
}
fun reset() {
synchronized (managedDelegates) {
managedDelegates.forEach { it.reset() }
managedDelegates.clear()
}
}
}
interface Resettable {
fun reset()
}
class ResettableLazy<PROPTYPE>(val manager: ResettableLazyManager, val init: ()->PROPTYPE): Resettable {
@Volatile var lazyHolder = makeInitBlock()
operator fun getValue(thisRef: Any?, property: KProperty<*>): PROPTYPE {
return lazyHolder.value
}
override fun reset() {
lazyHolder = makeInitBlock()
}
fun makeInitBlock(): Lazy<PROPTYPE> {
return lazy {
manager.register(this)
init()
}
}
}
fun <PROPTYPE> resettableLazy(manager: ResettableLazyManager, init: ()->PROPTYPE): ResettableLazy<PROPTYPE> {
return ResettableLazy(manager, init)
}
fun resettableManager(): ResettableLazyManager = ResettableLazyManager()
还有一些单元测试可以确定:
class Tester {
@Test fun testResetableLazy() {
class Something {
var seed = 1
val lazyMgr = resettableManager()
val x: String by resettableLazy(lazyMgr) { "x ${seed}" }
val y: String by resettableLazy(lazyMgr) { "y ${seed}" }
val z: String by resettableLazy(lazyMgr) { "z $x $y"}
}
val s = Something()
val x1 = s.x
val y1 = s.y
val z1 = s.z
assertEquals(x1, s.x)
assertEquals(y1, s.y)
assertEquals(z1, s.z)
s.seed++ // without reset nothing should change
assertTrue(x1 === s.x)
assertTrue(y1 === s.y)
assertTrue(z1 === s.z)
s.lazyMgr.reset()
s.seed++ // because of reset the values should change
val x2 = s.x
val y2 = s.y
val z2 = s.z
assertEquals(x2, s.x)
assertEquals(y2, s.y)
assertEquals(z2, s.z)
assertNotEquals(x1, x2)
assertNotEquals(y1, y2)
assertNotEquals(z1, z2)
s.seed++ // but without reset, nothing should change
assertTrue(x2 === s.x)
assertTrue(y2 === s.y)
assertTrue(z2 === s.z)
}
}
关于android - Kotlin 惰性属性和值重置 : a resettable lazy delegate,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35752575/
我是一名优秀的程序员,十分优秀!