SupportMapFragment Map is null

2019-03-05 03:42发布

问题:

I am using following code to display a map in Xamarin.Android:

private SupportMapFragment mapFragment;
private GoogleMap map;

protected override void OnCreate (Bundle bundle)
        {
            base.OnCreate (bundle);

            SetContentView (Resource.Layout.Main);

            mapFragment = SupportFragmentManager.FindFragmentByTag ("map") as SupportMapFragment;
            if (mapFragment == null) {
                GoogleMapOptions options = new GoogleMapOptions ()
                    .InvokeCompassEnabled (true)
                    .InvokeMapType (GoogleMap.MapTypeNone)
                    .InvokeZoomControlsEnabled (false);

                FragmentTransaction frx = SupportFragmentManager.BeginTransaction ();
                mapFragment = SupportMapFragment.NewInstance (options);
                frx.Add (Resource.Id.map,mapFragment,"map");
                frx.Commit ();
            }


if (map == null)
                map = mapFragment.Map;

            CircleOptions circle = new CircleOptions ();
            circle.InvokeCenter (new LatLng(18.5203,73.8567));
            circle.InvokeRadius (1000);
            map.AddCircle (circle);

and my AXML is

<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/map"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    class="com.google.android.gms.maps.SupportMapFragment" />

After successful deployment on device, it is giving me an exception on line map.AddCircle (circle); as System.NullReferenceException has been thrown Object Reference is not set to an instance of an Object.

What am I doing wrong? Is there something needed to be initialized?

回答1:

This line:

SupportFragmentManager.FindFragmentByTag ("map") as SupportMapFragment;

Should not work as you are trying to cast a View coming outside of Mono.Android. Hence you must use:

SupportFragmentManager.FindFragmentByTag<SupportMapFragment>("map");

or

SupportFragmentManager.FindFragmentByTag ("map").JavaCast<SupportMapFragment>();

Also you are trying to find a fragment by Tag. However, you didn't give your Fragment a Tag in your XML, so you need to find it by Id instead:

var mapFragment = SupportFragmentManager.FindFragmentById<SupportMapFragment>(Resource.Id.map);

Actually from the code you have pasted the line:

SupportFragmentManager.FindFragmentByTag ("map") as SupportMapFragment;

Will always be null, as you are actually ignoring the layout entirely, and you will always use the manually created SupportMapFragment in the if (mapFragment == null) condition...

Also, last time I checked, the bindings for the FindFragmentByXXX didn't support the generic type, so you will probably have to do the JavaCast<T>();

So, I would revise my code to look more like:

private SupportMapFragment mapFragment;
private GoogleMap map;

protected override void OnCreate (Bundle bundle)
{
    base.OnCreate (bundle);

    SetContentView (Resource.Layout.Main);

    SetUpMapIfNeeded();
}

public override void OnResume()
{
    base.OnResume();
    SetUpMapIfNeeded();
}

private void SetUpMapIfNeeded()
{
    if(null != map) return;

    mapFragment = SupportFragmentManager.FindFragmentById(Resource.Id.map).JavaCast<SupportMapFragment>();
    if (mapFragment != null)
    {
        map = mapFragment.Map;

        if (map == null)
        {
            // throw error here, should never happen though...
            return;
        }

        // set up map here, i.e.:
        map.UiSettings.CompassEnabled = true;
        map.MapType = GoogleMap.MapTypeHybrid;
        map.MyLocationChange += MapOnMyLocationChange;

        CircleOptions circle = new CircleOptions ();
        circle.InvokeCenter (new LatLng(18.5203,73.8567));
        circle.InvokeRadius (1000);
        map.AddCircle (circle);
    }
}