Kotlin从嵌套类中引用外部类

时间:2019-02-28 12:42:50

标签: android inheritance kotlin

我有一个类O和一个O内的嵌套类,称为N

N的功能中,我想通过使用this来引用O的{​​{1}}。

但是,只有当我使用this@O时,它才能识别O

但是,如果我使用内部类,则android-studio建议这样做可能会导致泄漏。

还有另一种引用外部类或避免泄漏的方法吗?

1 个答案:

答案 0 :(得分:2)

内存泄漏的可能性是由于inner类的每个实例都拥有对外部类的实例的引用而造成的。程序逻辑可能不需要该外部类实例,但是它仍然是可见的,因此不受垃圾回收的影响。

因此,如果您知道嵌套类实例可能不需要外部类实例的全部内容来支持其逻辑,则可以通过不使用inner类来确保不存在内存泄漏。

如果仍然需要外部类实例的某些部分,则可以将这些值手动传递给嵌套类实例:

class A {
    val b: B = someB()
    val c: C = someC()

    // D uses C but does not need B, so we pass C to the constructor:
    class D(private val c: C) { /* ... */ }

    fun createD(): D = D(c)
}

如果您还需要嵌套的类实例来观察外部类实例属性的变化(而不仅仅是在嵌套类实例构建时使用该属性的快照),则可以将该属性手动包装到引用持有者中,将该持有人传递给嵌套的类构造函数:

class A {
    val b: B = someB()

    private val cHolder = CHolder(someC())

    class CHolder(var c: C)

    var c: C
        get() = cHolder.c
        set(value) { cHolder.c = value }

    // D uses C but does not need B, so we pass C to the constructor:
    class D(private val cHolder: CHolder) { /* ... */ }

    fun createD(): D = D(cHolder)
}

如果这种模式在代码中重复出现,您可能希望使用某种通用解决方案来代替类CHolder;这只是一个演示。

然后,如果您要引用外部类的整个实例,则仍然可以选择将其传递给嵌套类的构造函数。与inner class相比,这使您可以手动控制外部实例的生存期,并在不需要时删除对它的引用:

class A {
    class D(private var outer: A?) {
        fun forgetOuterInstance() {
            outer = null
        }
    }

    fun createD(): D = D(this)
}

最后,如果嵌套类在其整个生命周期中都需要外部类实例,或者如果外部类不持有任何昂贵的资源,并且您可以处理其实例的可能更长的生存期,则可以使用inner class,只要记住,只要内部类实例可以运行,外部类实例就会保持活动状态。因此,您可能希望将一些资源移出外部类,以更精细的方式保留和释放它们。