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
innerkeyword 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 */ } }
}
}