android-maps-compose: Memory leak
I have mentioned this in https://github.com/googlemaps/android-maps-compose/issues/26 , but it is already closed, so I am opening a new issue. I am getting a leak if the map component is cleared and then the activity is destroyed.
Previously when implementing it through AndroidView, to get rid of the maps leak, I had to use:
DisposableEffect(lifecycle) {
lifecycle.addObserver(lifecycleObserver)
onDispose {
lifecycle.removeObserver(lifecycleObserver)
mapView.onDestroy()
mapView.removeAllViews()
}
}
And
remember(mapView) {
LifecycleEventObserver { _, event ->
when (event) {
Lifecycle.Event.ON_CREATE -> mapView.onCreate(Bundle())
Lifecycle.Event.ON_START -> mapView.onStart()
Lifecycle.Event.ON_RESUME -> mapView.onResume()
Lifecycle.Event.ON_PAUSE -> mapView.onPause()
Lifecycle.Event.ON_STOP -> mapView.onStop()
Lifecycle.Event.ON_DESTROY -> {
//handled in onDispose
}
else -> throw IllegalStateException()
}
}
}
The reason is that Lifecycle.Event.ON_DESTROY might not be called, and this way you would always dispose of the map view in onDispose, which will always be called. Would you be able to add this? I did fork and update it and the big memory leak disappeared.
`1 APPLICATION LEAKS
References underlined with "~~~" are likely causes.
Learn more at https://squ.re/leaks.
56446 bytes retained by leaking objects
Signature: 34a030bd011ab1ccd655bbeac3fbc8465c53ce5f
┬───
│ GC Root: Thread object
│
├─ com.google.maps.api.android.lib6.gmm6.vector.n instance
│ Leaking: UNKNOWN
│ Retaining 3.5 MB in 26933 objects
│ Thread name: 'RenderDrive'
│ ↓ n.e
│ ~
├─ com.google.maps.api.android.lib6.gmm6.vector.p instance
│ Leaking: UNKNOWN
│ Retaining 3.5 MB in 26930 objects
│ ↓ p.f
│ ~
├─ com.google.maps.api.android.lib6.gmm6.api.ac instance
│ Leaking: UNKNOWN
│ Retaining 3.5 MB in 26929 objects
│ View not part of a window view hierarchy
│ View.mAttachInfo is null (view detached)
│ View.mWindowAttachCount = 1
│ mContext instance of ExampleApplication
│ ↓ ac.N
│ ~
├─ com.google.maps.api.android.lib6.impl.ax instance
│ Leaking: UNKNOWN
│ Retaining 20 B in 1 objects
│ a instance of ExampleApplication
│ b instance of ExampleActivity with mDestroyed = true
│ ↓ ax.b
│ ~
╰→ ExampleActivity instance`
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 7
- Comments: 16 (16 by maintainers)
Commits related to this issue
- https://github.com/googlemaps/android-maps-compose/issues/138 과 비슷하게 코드를 수정합니다. — committed to bsscco/naver-map-compose by bsscco 2 years ago
- LazyColumn에서 사용 시 메모리 누수가 발생하여 수정요청 드립니다. (#24) * LazyColumn 안에서 스크롤 해서 NaverMap이 안 보이는 시점에 메모리 해제가 되지 않아 메모리릭이 발생하는 현상, AnimatedNavHost 안에서 NaverMap을 사용할 때 onDestroy()가 호출되지 않는 현상을 해결하기 위해 코드를 수정합니다... — committed to fornewid/naver-map-compose by bsscco 2 years ago
- https://github.com/googlemaps/android-maps-compose/issues/138 sample project — committed to polivmi1/android-maps-compose by polivmi1 2 years ago
- #138 - prevent a memory leak on AndroidView which may not call ON_DESTROY — committed to polivmi1/android-maps-compose by polivmi1 2 years ago
- #138 - prevent a memory leak on AndroidView which may not call ON_DESTROY — committed to polivmi1/android-maps-compose by polivmi1 2 years ago
- #138 - prevent a memory leak on AndroidView which may not call ON_DESTROY (#188) — committed to googlemaps/android-maps-compose by polivmi1 2 years ago
- Revert "#138 - prevent a memory leak on AndroidView which may not call ON_DESTROY (#188)" This reverts commit b87f837f3928747c761c4badd43412a2296bbd51. — committed to googlemaps/android-maps-compose by wangela 2 years ago
- Revert "#138 - prevent a memory leak on AndroidView which may not call ON_DESTROY (#188)" (#202) This reverts commit b87f837f3928747c761c4badd43412a2296bbd51. — committed to googlemaps/android-maps-compose by wangela 2 years ago
- Revert "Revert "#138 - prevent a memory leak on AndroidView which may not call ON_DESTROY (#188)" (#202)" This reverts commit 5183ce0d858f59964d93eac27473bb2ab755aa1a. — committed to googlemaps/android-maps-compose by wangela 2 years ago
- chore(release): 2.7.1 [skip ci] ## [2.7.1](https://github.com/googlemaps/android-maps-compose/compare/v2.7.0...v2.7.1) (2022-09-21) ### Reverts * Revert "#138 - prevent a memory leak on AndroidView... — committed to googlemaps/android-maps-compose by semantic-release-bot 2 years ago
- LazyColumn에서 사용 시 메모리 누수가 발생하여 수정요청 드립니다. (#24) * LazyColumn 안에서 스크롤 해서 NaverMap이 안 보이는 시점에 메모리 해제가 되지 않아 메모리릭이 발생하는 현상, AnimatedNavHost 안에서 NaverMap을 사용할 때 onDestroy()가 호출되지 않는 현상을 해결하기 위해 코드를 수정합니다... — committed to yU5295/map-compose by yU5295 2 years ago
@arriolac I have added a sample here https://github.com/polivmi1/android-maps-compose It contains 2 screens using compose navigation. Steps to reproduce the problem:
I am also attaching screenshots of the step 5 and 6:
Please let me know if you need more information. It should be clear from this, but you can also add the lifecycle logs and try with the fix I mentioned in the first comment.
Thanks for looking into it!
Ok I’ve confirmed that it is the intended behavior that the previous destination is not getting the DESTROYED event when navigating away from it. Your proposed workaround https://github.com/googlemaps/android-maps-compose/issues/138#issue-1263112472 should be put in place to resolve this @polivmi1. Would you like to make this contribution to the library?
I can confirm the memory leak and your proposed workaround does indeed fix the issue, however, I think the underlying lifecycle for the NavBackStackEntry should be receiving the ON_DESTROY event. Will raise this to the navigation compose team to see where the fix should be applied.
@arriolac this is a pretty standard project, where there is a map, marker and clicking the marker goes to other screen, clicking back button goes back. Using compose navigation. Unfortunately, I can’t share the big project where the leak is big, because it is private. I can add you these logs and create it in the sample to validate based on the lifecycle + you could add leakcanary and see the difference between this (will depend on the app data size, because it leaks it all) and the small google internal leak. I can create it if you need it, but first I wanted to sent you logs from such an app lifecycle, so you can see that in this case ON_DESTROY is never called and memory keeps leaking (the previous screen is on backstack until the back button is pressed and it is re-created):
(it would be called when we get back to the screen and everything would be cleared, but onDispose removes the listener when moving to screen B)