Android Maps V2 MapView inside custom fragment (NPE)

I do not want to use or extend SupportMapFragment or MapFragment. I have my own base class with a bunch of code in it.

The documentation clearly states that when someone uses MapView by itself, all corresponding lifecycle methods (onCreate() onResume() etc.) should be called.

Most of the lifecycle methods in a Fragment are similar to an Activity but when I switch back and forth between my Fragment I eventually get an obfuscated NPE in onDestroy() or in onResume() methods.

All the samples provided use an Activity with a MapView but not a custom Fragment.

Has someone done that already? Can you provide sample code of a MapView in your own Fragmentclass?

Answers


I succeeded in including a MapView (v2) in a custom Fragment itself embedded in a ViewPager. In my case, the MapView is included in the Fragment layout file. I have had to call lifecycle methods on MapView (onCreate() called onCreateView() from the Fragment), and to call manually MapsInitializer.initialize(context) to avoid a NullPointerException from class BitmapDescriptorFactory (to get the bitmap for markers). This last trick is strange, and I don't know why the Map system isn't properly initialized itself without this call, maybe it's just a bug in the current version ...

In my case I haven't had any NullPointerException in onResume() or onDestroy().


I struggled a bit with PoPy's answer but in the end I managed it and here is what I came up with. Probably this is helpful to others which will also come across this issue:

public class MyMapFragment extends Fragment {

    private MapView mMapView;
    private GoogleMap mMap;
    private Bundle mBundle;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View inflatedView = inflater.inflate(R.layout.map_fragment, container, false);

        try {
            MapsInitializer.initialize(getActivity());
        } catch (GooglePlayServicesNotAvailableException e) {
            // TODO handle this situation
        }

        mMapView = (MapView) inflatedView.findViewById(R.id.map);
        mMapView.onCreate(mBundle);
        setUpMapIfNeeded(inflatedView);

        return inflatedView;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mBundle = savedInstanceState;
    }

    private void setUpMapIfNeeded(View inflatedView) {
        if (mMap == null) {
            mMap = ((MapView) inflatedView.findViewById(R.id.map)).getMap();
            if (mMap != null) {
                setUpMap();
            }
        }
    }

    private void setUpMap() {
        mMap.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker"));
    }

    @Override
    public void onResume() {
        super.onResume();
        mMapView.onResume();
    }

    @Override
    public void onPause() {
        super.onPause();
        mMapView.onPause();
    }

    @Override
    public void onDestroy() {
        mMapView.onDestroy();
        super.onDestroy();
    }
}

And here is the corresponding res/layout/map_fragment.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <com.google.android.gms.maps.MapView
        android:id="@+id/map"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</RelativeLayout>

You can omit the RelativeLayout (and move the xmlns declartion up to your new root element, in this case the com.google.android.gms.maps.MapView) if you have just one element in your layout like in this example.


While using a separate MapView following two things are of vital importance

    //at Activity
    @Override
    protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      MapsInitializer.initialize(this);
      mapView.onCreate(savedInstanceState); 
    }
    //or at Fragment
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
                       Bundle savedInstanceState) {

       MapsInitializer.initialize(getActivity());  
       mapView.onCreate(mBundle);
     }
    //along with the following
    @Override
    protected void onResume() {
       super.onResume();
       if (mapView != null)
        mapView.onResume();
      }

    @Override
    protected void onDestroy() {
       super.onDestroy();
       if (mapView != null)
        mapView.onDestroy();
    }

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

Need Your Help

rmarkdown: pandoc: pdflatex not found

r macos pandoc pdflatex r-markdown

When I use the render{rmarkdown} to produce pdf file from .Rmd file on my Mac, an error message says

Arrow Operator vs. Dot Operator

c pointers structure

It seems to me that C's arrow operator (->) is unnecessary. The dot operator (.) should be sufficient. Take the following code: