Android Weak Reference In Inner Class

ID

kotlin.android_weak_reference_in_inner_class

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

Kotlin

Tags

android, reliability

Description

Reports inner class declarations nested inside an Activity or Fragment subclass. An inner class in Kotlin carries an implicit reference to its enclosing instance, so any long-lived inner instance pins the entire Activity (and its view hierarchy) in memory.

Rationale

class MyActivity : Activity() {

    inner class LeakyHandler {              // FLAW — captures the Activity
        fun doWork() { /* ... */ }
    }

    class StaticNested {                    // OK — no implicit outer reference
        fun doWork() { /* ... */ }
    }
}

The leak is invisible at the call site: posting a delayed message to a Handler defined as an inner class is enough to keep the entire Activity alive across a configuration change, doubling memory pressure and breaking lifecycle assumptions.

Remediation

Pick the option that matches your access needs:

  • Drop the inner keyword to make the class a static nested class. The compiler will then refuse any reference to the outer state.

  • If the inner instance genuinely needs access to the Activity, hold the reference through a WeakReference<Outer> so the garbage collector can reclaim the Activity when its lifecycle ends.

class MyActivity : Activity() {
    class SafeHandler(activity: MyActivity) {
        private val ref = java.lang.ref.WeakReference(activity)
        fun doWork() { ref.get()?.let { /* use it */ } }
    }
}