片段中的空指针异常,使用 google 映射

Null pointer exception in fragment, using google maps

我在片段中获取 android google 映射时收到空指针异常。错误在 findFragmentById.I 行尝试使用 if (mMap != null) 表示地图仍然为空。我该怎么做才能解决这个问题?

在MapActivity.java,

//Relevant imports
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
enter code here
public class MapView extends Fragment {

GoogleMap mMap;
LatLng mLocation = new LatLng(1.379348, 103.849876);

 @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {

        View rootView = inflater.inflate(R.layout.map_view, container, false);

        mMap = ((SupportMapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap(); 

        mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
        //Zoom
        mMap.getUiSettings().setZoomControlsEnabled(true);

        mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(mLocation, 17));
        Marker mMarker = mMap.addMarker(new MarkerOptions()
        .position(mLocation)
        .title("School")
        .snippet("NTU")
        .icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_launcher)));

        mMap.setOnMarkerClickListener(new OnMarkerClickListener()
        {
            public boolean onMarkerClick(Marker marker){
                Toast.makeText(getActivity().getApplicationContext(), "Welcome to " + marker.getTitle(), Toast.LENGTH_LONG);

                return false;
            }
        });

        mMap.setOnInfoWindowClickListener(new OnInfoWindowClickListener(){

            @Override
            public void onInfoWindowClick(Marker arg0) {
                // TODO Auto-generated method stub

            }
        });

        return rootView;
    }

}

在map_view.xml,

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >

<fragment
    android:id="@+id/map"
    android:name="com.google.android.gms.maps.MapFragment" 
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" />
</RelativeLayout>

为了将 SupportMapFragment 嵌套在片段中,您需要使用 getChildFragmentManager() 而不是 getFragmentManager()

所以,你会改变这个:

 mMap = ((SupportMapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();

为此,还将所有引用 mMap 的代码移动到 onResume():

 mMap = ((SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map)).getMap(); 

如果你走这条路,你还需要修复布局 xml 以使用 SupportMapFragment:

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

但是,如果不需要,最好不要嵌套 Fragment,因为它会导致 other problems

更好的方法是让 Fragment 扩展 SupportMapFragment。这样做,您甚至不需要布局 xml 文件。

示例:

public class MapView extends SupportMapFragment 
                                    implements OnMapReadyCallback {

    private GoogleMap mMap;
    private Marker marker;


    public MapView() {
    }

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

        setUpMapIfNeeded();
    }

    private void setUpMapIfNeeded() {

        if (mMap == null) {

            getMapAsync(this);
        }
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {

        mMap = googleMap;
        setUpMap();
    }

    private void setUpMap() {

        mMap.setMyLocationEnabled(true);
        mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
        mMap.getUiSettings().setMapToolbarEnabled(false);

    }


}

你可以这样试试吗?

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

Activity片段:

private GoogleMap mMap;
private MapView mapView;

在 onCreate() 上:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
     View rootView = inflater.inflate(R.layout.fragment_map,container, false)
     initializaMap(rootView, savedInstanceState);
   return rootView;
}

onResume()

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

    }

on onDestroy()

    @Override
    public void onDestroy() {

        if(mapView!=null){
            mapView.onDestroy();
        }

        super.onDestroy();
    }

on onLowMemory()

@Override
    public void onLowMemory() {

        if(mapView!=null){
            mapView.onLowMemory();
        }

        super.onLowMemory();
    }

添加新方法:

private void initializaMap(View rootView, Bundle savedInstanceState){
        MapsInitializer.initialize(getActivity());
        switch (GooglePlayServicesUtil.isGooglePlayServicesAvailable(getActivity())) {
            case ConnectionResult.SUCCESS:
                mapView = (MapView) rootView.findViewById(R.id.mapView);
                mapView.onCreate(savedInstanceState);

                if (mapView != null) {
                    mMap = mapView.getMap();
                    mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
                    UiSettings mUiSettings = mMap.getUiSettings();
                    mMap.setMyLocationEnabled(true);
                    mMap.animateCamera(CameraUpdateFactory.zoomTo(zoomLevel));
                    mUiSettings.setCompassEnabled(true);
                    mUiSettings.setMyLocationButtonEnabled(false);
                    mMap.setOnMarkerClickListener(this);
                }
                break;
            case ConnectionResult.SERVICE_MISSING:
                break;
            case ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED:
                break;
            default:
        }
    }

希望对您有所帮助。