MapView - Leak memory

813
4
02-12-2023 08:19 PM
MinhPham92
New Contributor

Hi all,
I am facing a leak memory as logged below, I am using leak canary to found that.
I already called mapView.dispose() and see the log "TextureView RenderingThread - disposed" before leak canary dump the memory. Could you please help to take a look ?
Thanks a lot.

├─ Dalvik.system.PathClassLoader instance
2 │ Leaking: NO (b↓ is not leaking and A ClassLoader is never leaking)
3 │ ↓ ClassLoader.runtimeInternalObjects
4 ├─ java.lang.Object[] array
5 │ Leaking: NO (b↓ is not leaking)
6 │ ↓ Object[731]
7 ├─ com.esri.arcgisruntime.internal.b.b class
8 │ Leaking: NO (a class is never leaking)
9 │ ↓ static b.WRAPPER_CACHE
10 │ ~~~~~~~~~~~~~
11 ├─ com.esri.arcgisruntime.internal.b.h instance
12 │ Leaking: UNKNOWN
13 │ Retaining 4.2 MB in 115754 objects
14 │ ↓ h.mCache
15 │ ~~~~~~
16 ├─ java.util.concurrent.ConcurrentHashMap instance
17 │ Leaking: UNKNOWN
18 │ Retaining 4.2 MB in 115753 objects
19 │ ↓ ConcurrentHashMap[instance @319226872 of java.lang.Long]
20 │ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
21 ├─ com.esri.arcgisruntime.internal.h.b.g$b instance
22 │ Leaking: UNKNOWN
23 │ Retaining 4.2 MB in 115749 objects
24 │ ↓ g$b.a
25 │ ~
26 ├─ com.esri.arcgisruntime.internal.h.b.o instance
27 │ Leaking: UNKNOWN
28 │ Retaining 4.2 MB in 115740 objects
29 │ ↓ g.mGeoView
30 │ ~~~~~~~~
31 ├─ com.esri.arcgisruntime.mapping.view.MapView instance
32 │ Leaking: YES (View.mContext references a destroyed activity)
33 │ Retaining 551.2 kB in 9727 objects
34 │ View not part of a window view hierarchy
35 │ View.mAttachInfo is null (view detached)
36 │ View.mID = R.id.mapView
37 │ View.mWindowAttachCount = 1
38 │ mContext instance of com......MyActivity with mDestroyed = true
39 │ ↓ View.mContext
40 ╰→ com........MyActivity instance
41 ​ Leaking: YES (ObjectWatcher was watching this because com.......MyActivity received
42 ​ Activity#onDestroy() callback and Activity#mDestroyed is true)
43 ​ Retaining 207.4 kB in 3681 objects
44 ​ key = b5f097e7-68d9-4e29-ab0b-d96684f9cfa0
45 ​ watchDurationMillis = 5266
46 ​ retainedDurationMillis = 233
47 ​ mApplication instance of com......MyApplication
48 ​ mBase instance of androidx.appcompat.view.ContextThemeWrapper

 

0 Kudos
4 Replies
Shubham_Sharma
Esri Contributor

@MinhPham92 Seems like you are accessing the MapView by calling dispose() after the activity is destroyed (or context is lost) based on the log messages:

Leaking: YES (View.mContext references a destroyed activity)

 

Suggest calling dispose() before destroying the activity.

override fun onDestroy() {
    mapView.dispose()
    super.onDestroy()
}

override fun onPause() {
    mapView.pause()
    super.onPause()
}

override fun onResume() {
    super.onResume()
    mapView.resume()
}

 

0 Kudos
MinhPham92
New Contributor

hi @Shubham_Sharma ,
Thanks for your response, but actually, I am calling mapView.dispose() on onDestroyView of Fragment and before super(). 

Leaking: YES (View.mContext references a destroyed activity)

 For the log above, you can see the geoView is referencing to a destroyed activity, in case we call mapView.dispose after destroy, it should throw null pointer exception

0 Kudos
MinhPham92
New Contributor

Does any one have any idea ?

I am using version 100.14

My exactly scenario:
I have an activityA -> contains fragmentA -> fragmentA contains MapFragment which has map view.
When MapFragment destroy view, I call mapView.dispose() before super and I already see the log TextureView RenderingThread - disposed, but after that, I see Rendering Thread is still keeping reference to activity context.

0 Kudos
MinhPham92
New Contributor

Finally, I found the root cause, the root cause actually come from missing dispose map view, but it behinds another root cause as a scenario below:
1. I have 2 xml files: `fragment_A.xml` has the map view, and another `fragment_B.xml` has the map view also
2. In MapFragment, I bind view with fragment_A.xml, and using ConstraintSet to clone the arrangement between view component in fragment_B.xml. After that, I used `TransitionManager` to do the animation between 2 layouts.
Unfortunately, when ConstraintSet do clone, it inflate the view, so the map view created via this step also. But we didn't aware about that.
So to resolve this, after ConstrainSet clone, we need to manually call dispose for map view 
Finally, totally, we need to aware how many time we init the view which contains map view, we need to call dispose as the same quantity

0 Kudos