5

Nous essayons de localiser une fuite de mémoire qui se produit sur le GoogleMap dans notre application Android, qui se termine dans un MOO après environ 40-50 rotations de périphériques. La carte est définie autour de 3500 marqueurs. L'App a un minSDK de 9 et utilise donc le SupportMapFragment de la V4 Support Library.Android Maps V2 fuite de mémoire LocationClientHelper

Nous avons essayé plusieurs choses, notamment:

  • Mise en cache le
  • Mise en cache de LatLng CameraUpdates
  • Suppression des marqueurs de carte
  • Suppression des écouteurs de carte
  • Suppression de tous les auditeurs, marqueurs, etc. afin que nous avons juste une carte
  • Mise à jour de la bibliothèque Google Play Services
  • Mise à jour de la bibliothèque de soutien

Analyse du vidage de la mémoire en MAT montre que nous accumulons beaucoup de cas de com.google.android.gms.location.internal.LocationClientHelper$ListenerTransport que nous avons aucune idée d'où ils viennent.

Quelqu'un a une idée sur ce qui pourrait être la cause de cette fuite de mémoire?

Le code suivant a déjà tous les lecteurs et les écouteurs supprimés et fuit toujours. Tout d'abord la classe de base:

public abstract class BaseMapFragment extends Fragment { 

public static final int MENU_ITEM_ID_SEARCH= 102; 
public static final int MENU_ITEM_ID_SHOW_LIST= 100; 
public static final int ZOOM_LEVEL_DEFAULT= 14; 

private static final String SAVED_INSTANCE_LATITUDE= "savedLatitude"; 
private static final String SAVED_INSTANCE_LONGITUDE= "savedLongitutde"; 
private static final String SAVED_INSTANCE_ZOOM= "savedZoom"; 

protected static final String CLASSTAG= BaseMapFragment.class.getSimpleName(); 

private GoogleMap mMap; 
private CameraUpdate mResumeCameraUpdate= null; 
private double mSavedLatitude; 
private double mSavedLongitude; 
private float mSavedZoom; 
private static View mView; 

@Override 
public void onSaveInstanceState(Bundle outState) { 
    super.onSaveInstanceState(outState); 
    if (mMap != null) { 
     outState.putDouble(SAVED_INSTANCE_LATITUDE, mMap.getCameraPosition().target.latitude); 
     outState.putDouble(SAVED_INSTANCE_LONGITUDE, mMap.getCameraPosition().target.longitude); 
     outState.putFloat(SAVED_INSTANCE_ZOOM, mMap.getCameraPosition().zoom); 
    } 
} 

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
    super.onCreateView(inflater, container, savedInstanceState); 
    if (savedInstanceState != null) { 
     mSavedLatitude= savedInstanceState.getDouble(SAVED_INSTANCE_LATITUDE, Constants.EXTRA_VALUE_NONE); 
     mSavedLongitude= savedInstanceState.getDouble(SAVED_INSTANCE_LONGITUDE, Constants.EXTRA_VALUE_NONE); 
     mSavedZoom= savedInstanceState.getFloat(SAVED_INSTANCE_ZOOM, Constants.EXTRA_VALUE_NONE); 
    } 

    if (mView != null) { 
     ViewGroup parent= (ViewGroup) mView.getParent(); 
     if (parent != null) 
      parent.removeView(mView); 
    } 
    try { 
     mView= inflater.inflate(R.layout.map_layout, container, false); 
    } catch (InflateException e) { 
     /* map is already there, just return view as it is */ 
    } 
    return mView; 
} 

protected GoogleMap initializeMap() { 
    if (mMap != null) { 
     if (mSavedLatitude != Constants.EXTRA_VALUE_NONE && mSavedLatitude != 0.0) { 
      mResumeCameraUpdate= Context.getCamUpdate(mSavedZoom, mSavedLatitude, mSavedLongitude); 
     } else { 
      mResumeCameraUpdate= Context.getCamUpdate(mMap.getCameraPosition().zoom, mMap.getCameraPosition().target.latitude, mMap.getCameraPosition().target.longitude); 
     } 
    } 

    SupportMapFragment mapFragment= (SupportMapFragment) getActivity().getSupportFragmentManager().findFragmentById(R.id.map); 
    if (mapFragment == null) { 
     mapFragment= (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map); 
     if (mapFragment == null) { 
      MapsInitializer.initialize(getActivity()); 
      mapFragment= SupportMapFragment.newInstance(); 
      mMap= mapFragment.getMap(); 
     } else { 
      mMap= mapFragment.getMap(); 
     } 
    } else { 
     mMap= mapFragment.getMap(); 
    } 

    // check if map is created successfully or not 
    if (mMap == null) { 
     Toast.makeText(getActivity().getApplicationContext(), R.string.map_create_unable, Toast.LENGTH_SHORT).show(); 
    } else { 
     mMap.setMyLocationEnabled(true); 
     mMap.setOnMyLocationButtonClickListener(new OnMyLocationButtonClickListener() { 
      @Override 
      public boolean onMyLocationButtonClick() { 
       if (mMap.getMyLocation() != null) { 
        CameraUpdate newLatLngZoom= Context.getCamUpdate(ZOOM_LEVEL_DEFAULT, mMap.getMyLocation()); 
        mMap.animateCamera(newLatLngZoom); 
       } else { 
        Toast.makeText(getActivity().getApplicationContext(), R.string.map_location_services_disabled, Toast.LENGTH_SHORT).show(); 
       } 
       return true; 
      } 
     }); 

    } 
    return mMap; 
} 

} 

Sous

public class MySupportMapFragment extends BaseMapFragment { 

private LinearLayout mStaoButtonsLayout; 
private ToggleButton mStaoButton; 
private ToggleButton mGasStaoButton; 

private Boolean mInitialLocationChange; 
private CameraUpdate mResumeCameraUpdate; 
private GoogleMap mMap; 
private double mBundleLatitude; 
private double mBundleLongitude; 


@Override 
public void addRequiredModelClasses(LinkedHashSet<Class<? extends ComergeModel<?>>> set) { 
    set.add(AboModel.class); 
    set.add(StationModel.class); 
    super.addRequiredModelClasses(set); 
} 

@Override 
public void onSaveInstanceState(Bundle outState) { 
    super.onSaveInstanceState(outState); 
    outState.putDouble(BUNDLE_EXTRA_CENTER_LATITUDE, mBundleLatitude); 
    outState.putDouble(BUNDLE_EXTRA_CENTER_LONGITUDE, mBundleLongitude);   
} 


@Override 
public void onActivityCreated(final Bundle savedInstanceState) { 
    super.onActivityCreated(savedInstanceState); 
    setHasOptionsMenu(showSearchButton()); 

    final StationModel stationModel= getContext().getModel(StationModel.class); 

    mStaoButtonsLayout= (LinearLayout) getActivity().findViewById(R.id.mapStaoButtons); 
    mStaoButtonsLayout.setVisibility(View.VISIBLE); 
    mStaoButton= (ToggleButton) mStaoButtonsLayout.findViewById(R.id.staoButton); 
    mStaoButton.setChecked(stationModel.isStationButtonChecked()); 
    mGasStaoButton= (ToggleButton) mStaoButtonsLayout.findViewById(R.id.gasStaoButton); 
    mGasStaoButton.setChecked(stationModel.isGasStationButtonChecked()); 

    mMap= initializeMap(); 
} 

@Override 
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 
    super.onCreateOptionsMenu(menu, inflater); 
    addSearchButton(menu); 
} 

} 
+0

S'agit-il d'une fuite de mémoire dans l'une des classes google? – byemute

+0

Problème Google Maps ouvert: https://code.google.com/p/gmaps-api-issues/issues/detail?can=2&start=0&num=100&q=&colspec=ID%20Type%20Status%20Introduced%20Fixed%20Summary% 20Stars% 20ApiType% 20Internal & groupby = & sort = & id = 8446 – byemute

Répondre

9

J'ai eu un problème similaire avant. J'ajouté du code ci-dessous pour résoudre mon problème:

@Override 
public void onDestroy() { 
    if (mMap != null) { 
     mMap.setMyLocationEnabled(false); 
    } 
} 

Il semble que LocationClientHelper $ ListenerTransport est liée à setMyLocationEnabled(). J'ai dû annuler l'enregistrement de certains rappels pour éviter les fuites de mémoire.

+1

Vous mon ami, méritez une médaille! Merci! De plus, nous avons annulé les écouteurs qui sont placés sur la carte et il semble avoir résolu le problème! – SOERGI

+1

Mec, vous êtes génial! Je vous donnerais des centaines de upvotes pour ça! Nous allons aussi signaler ceci à google car c'est drôle! – byemute

+1

Merci de partager cela! Cela fixe finalement la fuite! Vous méritez un câlin de notre part :) – byemute