fix(android): avoid retaining activity in Coil singleton factory#6403
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
💤 Files with no reviewable changes (1)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughCoil singleton image-loader configuration moves from Compose setup into ChangesCoil singleton integration
Estimated code review effort: 2 (Simple) | ~10 minutes 🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@androidApp/src/test/kotlin/org/meshtastic/app/CoilImageLoaderLifecycleTest.kt`:
- Around line 35-36: Update CoilImageLoaderLifecycleTest to use
`@Config`(application = MeshUtilApplication::class) and exercise Robolectric’s
production application lifecycle instead of manually constructing
MeshUtilApplication. Verify after startup that SingletonImageLoader.Factory
resolves the configured image loader, covering the app’s startKoin and Coil
factory wiring.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 8880d732-2672-4e6b-a877-c23f6d50d854
📒 Files selected for processing (3)
androidApp/src/main/kotlin/org/meshtastic/app/MainActivity.ktandroidApp/src/main/kotlin/org/meshtastic/app/MeshUtilApplication.ktandroidApp/src/test/kotlin/org/meshtastic/app/CoilImageLoaderLifecycleTest.kt
💤 Files with no reviewable changes (1)
- androidApp/src/main/kotlin/org/meshtastic/app/MainActivity.kt
5849116 to
6a02aef
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@androidApp/src/test/kotlin/org/meshtastic/app/CoilImageLoaderLifecycleTest.kt`:
- Line 33: Add the Coil DelicateCoilApi opt-in to the tearDown method that calls
SingletonImageLoader.reset(), preserving the existing `@After` annotation and
teardown behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 42ed181c-a0ff-4678-aef1-4dec55799ed5
📒 Files selected for processing (3)
androidApp/src/main/kotlin/org/meshtastic/app/MainActivity.ktandroidApp/src/main/kotlin/org/meshtastic/app/MeshUtilApplication.ktandroidApp/src/test/kotlin/org/meshtastic/app/CoilImageLoaderLifecycleTest.kt
💤 Files with no reviewable changes (1)
- androidApp/src/main/kotlin/org/meshtastic/app/MainActivity.kt
🚧 Files skipped from review as they are similar to previous changes (1)
- androidApp/src/main/kotlin/org/meshtastic/app/MeshUtilApplication.kt
Replace the per-Activity ImageLoaderFactory with a singleton-factory pattern in MeshUtilApplication to prevent retaining stale Activity references through configuration changes. Add a Robolectric lifecycle test exercising the real MeshUtilApplication, and opt into Coil's DelicateCoilApi for controlled global-state singleton reset in test teardown.
6a02aef to
8664f80
Compare
jamesarich
left a comment
There was a problem hiding this comment.
Verified the pieces that could break this:
org.koin.android.ext.android.getis already imported and used inMeshUtilApplication.kt, soget<ImageLoader>()resolves.GoogleMeshUtilApplicationextendsMeshUtilApplication, so both flavors inheritnewImageLoader.- No Koin leak across Robolectric classes:
onTerminate()already callsstopKoin()(MeshUtilApplication.kt:147), and Robolectric drivesonTerminateat teardown. newImageLoaderis invoked lazily on first image load, always afteronCreatestarts Koin.
One thing worth adding to the description, since it is a real improvement that is easy to miss: setSingletonImageLoaderFactory only bridged Compose call sites, whereas SingletonImageLoader.Factory on the Application covers all process-wide Coil use — including Glance/widget and any non-Compose loads, which previously fell back to a default ImageLoader with no custom HttpClient or SVG decoder.
Approving; queued to merge on green.
Overview
This moves Coil's process-wide singleton
ImageLoaderfactory fromMainActivitytoMeshUtilApplication.Registering the singleton factory from activity composition allowed the process-wide factory lambda to capture an activity instance. Recreating the activity could therefore leave the destroyed activity and its associated UI graph reachable through Coil's singleton configuration.
The application now owns the singleton factory and continues to return the existing Koin-configured
ImageLoader.Key Changes
SingletonImageLoader.FactoryonMeshUtilApplication.ImageLoaderfrom application scope.MainActivity.Testing
Runtime validation repeatedly paused, stopped, restarted, and resumed
MainActivityin the same process without image-loader initialization errors or process replacement. This exercises the lifecycle pattern that previously allowed activity ownership to leak into the process-wide singleton.Migration Notes
Summary by CodeRabbit
Bug Fixes
Tests