-
Notifications
You must be signed in to change notification settings - Fork 60
Open
Description
Summary
FileKit library retains a reference to ActivityResultRegistry through a static field in FileKitDialog, preventing Android Activities from being garbage collected after they are destroyed.
Environment
- Library Version:
filekit-core0.12.0 - Platform: Android (iOS not tested)
Steps to Reproduce
- Call
FileKit.init(activity)on a screen - Navigate away from the screen or close the app
- Activity remains in memory and is not garbage collected
Leak Trace
LeakCanary reports the following retention chain:
GC Root: Thread object
├─ android.net.ConnectivityThread instance
│ ↓ Thread.contextClassLoader
├─ dalvik.system.PathClassLoader instance
│ ↓ ClassLoader.runtimeInternalObjects
├─ java.lang.Object[] array
│ ↓ Object[3968]
├─ io.github.vinceglb.filekit.dialogs.FileKitDialog class
│ ↓ static FileKitDialog._registry
│ ~~~~~~~~~
├─ androidx.activity.ComponentActivity$activityResultRegistry$1 instance
│ Retaining 615.5 kB in 12731 objects
│ Anonymous subclass of androidx.activity.result.ActivityResultRegistry
│ this$0 instance of com.vinted.carrier.MainActivity with mDestroyed = true
│ ↓ ComponentActivity$activityResultRegistry$1.this$0
│ ~~~~~~
╰→ com.vinted.carrier.MainActivity instance
Leaking: YES (ObjectWatcher was watching this because com.vinted.carrier.MainActivity received
Activity#onDestroy() callback and Activity#mDestroyed is true)
Retaining 608.6 kB in 12497 objects
key = 9de4ea76-92f4-4034-9094-ec25f65f0546
watchDurationMillis = 5546
retainedDurationMillis = 530
Assumed Root Cause
The FileKitDialog object maintains a static reference to ActivityResultRegistry:
internal object FileKitDialog {
private var _registry: ActivityResultRegistry? = null
val registry: ActivityResultRegistry
get() = _registry
?: throw FileKitNotInitializedException()
fun init(registry: ActivityResultRegistry) {
_registry = registry
}
}Assumed problem:
FileKit.init(activity)setsFileKitDialog._registry = activity.activityResultRegistry- The
ActivityResultRegistryholds a reference to the Activity (this$0) - The static
_registryfield persists for the lifetime of the class - When the Activity is destroyed, the static reference prevents the
ActivityResultRegistryfrom being garbage collected - The
ActivityResultRegistryretains the Activity, preventing it from being garbage collected - There appears to be no cleanup mechanism to clear the
_registryreference when the Activity is destroyed
Metadata
Metadata
Assignees
Labels
No labels