Android MapView v2 Contextual Issues and Memory Leak

I use MapView v2 in my application (not MapFragment ), which causes a memory leak. A leak occurs when I pass an Activity context to the MapView constructor. If I pass the application context to the MapView constructor, the memory leak will disappear, however, MapView starts to work poorly when scrolling through the ScrollView.

Here is a snapshot where the leak occurs:

enter image description here

Relevant code in MapView :

 public class MapView extends android.widget.FrameLayout { private final com.google.android.gms.maps.MapView.b gD; static class b extends com.google.android.gms.dynamic.a<com.google.android.gms.maps.MapView.a> { private final android.content.Context mContext; // Here the Context MapView is leaking } static class a implements com.google.android.gms.dynamic.LifecycleDelegate { // More stuff in here } } 

I've been messing with MapView for several weeks MapView , trying to get it to behave properly in ScrollView , but to no avail. I'm going to give it up.

Also, the recently added snapshot() method is not an option, because I have already tried it and it does not give a reliable map snapshot. I have an open question about this here , as well as another open question here and here , all of which were not answered.

+2
source share
5 answers

Positively linked to danielgomezrico's answer , there is a confirmed error related to my location layer in MapView that is losing memory.

The workaround is to disable my location using GoogleMap.setMyLocationEnabled(false) before the map is destroyed. Also be sure to call other card life cycle methods.

 private MapView mMapView; private GoogleMap mMap; ... @Override public void onResume() { super.onResume(); mMapView.onResume(); } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); mMapView.onSaveInstanceState(outState); } @Override public void onPause() { super.onPause(); mMapView.onPause(); } @Override public void onLowMemory() { super.onLowMemory(); mMapView.onLowMemory(); } @Override public void onDestroy() { super.onDestroy(); if (mMap != null) { mMap.setMyLocationEnabled(false); } mMapView.onDestroy(); } 
+3
source

I've been messing with MapView for several weeks now, trying to get it to behave properly in ScrollView, but to no avail. I'm going to give it up.

Honestly, this is for the best. MapView will probably never play nicely inside ScrollView. There are many errors that occur when using this combination; vertical lag, rendering MapView over an ActionBar, vertical scrolling just doesn't work, etc. Removing ScrollView is not only preferable, but most likely required.

However, if you absolutely must do this, due to client restrictions, for example, you have two options.

  • You can use Snapshot and Snapshot callback; on callback, replace MapView with ImageView of the snapshot. You lose interactivity, but also lose the problems you encounter. (You claim that this does not work or draws an incomplete bitmap, although I did not encounter this problem. I'm not sure how you implement it.)

  • Write a custom class that extends MapView, override onTouchEvent and any motion events that need to be fixed (possibly ACTION_DOWN and ACTION_UP ), manually control whether the parent (ScrollView) can intercept the action. Use something like this.getParent().requestDisallowInterceptTouchEvent(true|false) depending on your case. For more information about this Android docs method,

I hope this helps!

+2
source

In the project in which I worked, we had a similar problem. We used mapView inside the viewholder. The solution was to call onPause and then onDestroy on mapview. After this, memory leaks were not observed.

+2
source

Do you use it inside a fragment? Perhaps related to this error https://code.google.com/p/android/issues/detail?id=185902

+2
source

Although I would prefer to use GoogleMap.setMyLocationEnabled() , this did not work in my case, so I decided to try mContext null and it worked:

 // Make sure to use View, not MapView Field contextField = View.class.getDeclaredField("mContext"); contextField.setAccessible(true); contextField.set(mapView, null); 
0
source

Source: https://habr.com/ru/post/1012297/


All Articles