Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MapView leaks activity (without location service)

I'm using the play services v9.8.0 (without location service permissions) and am still facing a leak when I use a MapView in a dialog fragment. I'm using it like in my code example and I use it to display a location only and I DON'T have setMyLocationEnabled (as I don't even have the permissions for this setting).

Does anyone see a problem in my code? I'm getting a leak like the one here: MapView v2 keeping Context around. I do following:

  • create a dialog
  • replace a view in my layout with a MapView (because I allow to use static maps as well, so my default view is a ImageView in my layout, that will be replaced with a MapView)

Then it happens that my fragments leaks MapView.mContext...

Code - Dialog Fragment

public class DialogMediaDetails extends DialogFragment
{
    private GoogleMap mGoogleMap = null;
    private MapView mMapView = null;

    @Override
    public final Dialog onCreateDialog(Bundle savedInstanceState)
    {
        Dialog dlg = ...; // create dialog
        View view = ...; // get view from dialog
        Location location = ...; // defined location
        initGoogleMap();
        return dlg;
    }

    private void initGoogleMap(Location location)
    {
        mMapView = new MapView(getActivity());
        MapsInitializer.initialize(getActivity());
        // Updates the location and zoom of the MapView
        mMapView.onCreate(null);
        mMapView.getMapAsync(new OnMapReadyCallback()
        {
            @Override
            public void onMapReady(GoogleMap googleMap)
            {
                LatLng coordinates = new LatLng(location.getLatitude(), location.getLongitude());
                googleMap.addMarker(new MarkerOptions().position(coordinates));
                googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(coordinates, 15));
                mGoogleMap = googleMap;
                mMapView.onResume();
            }
        });
        mMapView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener()
        {
            @Override
            public void onGlobalLayout()
            {
                mMapView.getViewTreeObserver().removeOnGlobalLayoutListener(this);

                // MapView is scrollable, so we disable dragging
                CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
                AppBarLayout.Behavior behavior = (AppBarLayout.Behavior) params.getBehavior();
                behavior.setDragCallback(new AppBarLayout.Behavior.DragCallback() {
                    @Override
                    public boolean canDrag(AppBarLayout appBarLayout) {
                        return false;
                    }
                });
            }
        });

        replaceHeader(mMapView);
    }

    private void replaceHeader(View view)
    {
        ViewGroup parent = (ViewGroup) pbHeader.getParent();
        int index = parent.indexOfChild(pbHeader);
        ViewGroup.LayoutParams lp = pbHeader.getLayoutParams();
        parent.removeView(pbHeader);
        parent.addView(view, index, lp);
    }

    // ----------------------------------------
    // forward all lifecycle events to MapView
    // ----------------------------------------

    @Override
    public void onResume() {
        super.onResume();
        if (mMapView != null)
            mMapView.onResume();
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        if (mMapView != null)
            mMapView.onSaveInstanceState(outState);
    }

    @Override
    public void onPause() {
        super.onPause();
        if (mMapView != null)
            mMapView.onPause();
    }

    @Override
    public void onLowMemory() {
        super.onLowMemory();
        if (mMapView != null)
            mMapView.onLowMemory();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mMapView != null)
            mMapView.onDestroy();
        mMapView = null;
    }
}
like image 954
prom85 Avatar asked Nov 14 '16 07:11

prom85


1 Answers

There are some issues reported about leaks with MapView. You may try calling googleMap.setMyLocationEnabled(false); in onDestroy to prevent the leak from happening. Failure to call either MapView.onDestroy or GoogleMap.setMyLocationEnabled(false) will cause a leak. Here's a related thread which might help.

like image 157
abielita Avatar answered Nov 11 '22 18:11

abielita