MapFragment 在 getMapAsync(this) 方法中导致 NullPointerException

MapFragment causing NullPointerException at getMapAsync(this) method

我实现了 activity,它在 运行 时添加了 MapFragmentMapFragment xml 具有静态 fragment,我正试图在 运行 时添加。我还发现 Lollipop 在 运行 时间添加地图片段时存在一些问题。请检查 Issue raised and temporary solution

我也在下面给出了我的代码,

fragment_map.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
         xmlns:tools="http://schemas.android.com/tools"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         tools:context=".fragment.MapsFragment">

<fragment
    android:id="@+id/map"
    android:name="com.google.android.gms.maps.SupportMapFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="appCreators.bloodfinder.activity.MapsActivity"/>

<include
    android:id="@+id/layout"
    layout="@layout/template_custom_spinner"/>

</FrameLayout>

MapsFragment.java

实施onMapReadyCallback

public class MapsFragment extends SupportMapFragment implements OnMapReadyCallback

onResume回调中

@Override
public void onResume() {
    super.onResume();
    ((SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map)).getMapAsync(this);
}

这个总是return我是空的,我也试过了,

((SupportMapFragment) getActivity().getSupportFragmentManager().findFragmentById(R.id.map)).getMapAsync(this);

这也是returnNullPointerException

MapsActivity.java

getSupportFragmentManager().beginTransaction().add(R.id.fragmentContainer, MapsFragment.newInstance()).commit();

我在 Activity 回调的 onCreate 方法中添加了这个。

我不明白为什么我仍然得到 NullPointerException

有时我得到 Attempt to invoke interface method 'void com.google.maps.api.android.lib6.e.fl.o()' on a null object reference

不胜感激!

更新: 仍未修复 我收到以下错误。我查看了日志,但不知道为什么会这样。

Unable to resume activity {MapsActivity}: java.lang.NullPointerException: Attempt to invoke interface method 'void com.google.maps.api.android.lib6.e.fl.o()' on a null object reference

不久前我一直在为类似的问题而苦苦挣扎。 关键是 getMap() 在适当的时候,在 FragmentonViewCreated():

public class LocationFragment extends Fragment {

    private SupportMapFragment locationMap;
    private View rootView;

    protected View getFragmentView() {
        View view = getView();
        if (view == null) {
            view = rootView;
        }
        return view;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View rootView = getFragmentView();
        if (rootView != null) {
            ViewGroup parent = (ViewGroup) rootView.getParent();
            if (parent != null) {
                parent.removeView(rootView);
            }
        }

        try {
            rootView = inflater.inflate(R.layout.fragment_signup_specify_location, container, false);
        } catch (InflateException ex) {
            Log.e(LOG_TAG, "Inflate Exception in onCreateView; Caused by map fragment", ex);
        }
        ......
        return getFragmentView();
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        locationMap = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.locationMap);
        if (locationMap != null) {
            LocationManager locationManager = (LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE);
            if (locationManager != null && locationMap.getMap() != null) {
                locationMap.getMap().setMyLocationEnabled(true);
            }
        }
    }
}

XML 看起来像你的:

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <fragment
        android:id="@+id/locationMap"
        android:layout_above="@+id/locationLabelTextView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:name="com.google.android.gms.maps.SupportMapFragment" />
</FrameLayout>

然后,在 onViewCreated() 中,您可以通知 Activity,您的 map-fragment 可以使用了。

希望对你有所帮助

通过观察 SO 中给出的答案,我终于自己解决了这个问题。我比较了我的代码和答案中的代码。在我看来,API 和 Google 的实施范围很广,有些混乱。我反复抛出这个异常:

Attempt to invoke interface method 'void com.google.maps.api.android.lib6.e.fl.o()' on a null object reference

我仍然不知道在出现相同异常的 SO 问题中的某些实现有什么问题,但这对我有用,可能对其他人也有用。

这些是您需要检查的内容:

  1. 确保你有这两个(我只有 api 键 meta-data)

        <meta-data
            android:name="com.google.android.geo.API_KEY"
            android:value="@string/google_maps_key" />
        <meta-data
            android:name="com.google.android.gms.version"
            android:value="@integer/google_play_services_version" />
    
  2. 您在 xml 中有一个这样的片段,class 属性正确,如下所示

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

在我的例子中,地图片段是一个子片段,在另一个片段中。

这个父片段显然不应该是 MapFragment 或 SupportMapFragment。将其从 SupportMapFragment 更改为 Fragment 后,地图显示完全正常。

public class ParentFragment extends Fragment {

我保留了之前的所有其他内容,但我没有在 onCreateView 中获取地图,而是在 onViewCreated 中获取地图,如下所示:

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);

    mapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.rewards_google_map_area);
    if (mapFragment != null) {
        LocationManager locationManager = (LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE);
        if (locationManager != null && mapFragment.getMap() != null) {
            googleMap=mapFragment.getMap();
            //after this you do whatever you want with the map
        }
    }

}

我没有更改任何其他内容,也没有弄乱 rootView 或 parentView。正如您在@Konstantin Loginov

的回答中看到的那样

试试看然后告诉我。

在我的例子中,我在片段的 xml 中静态使用原始 MapView。问题是我不得不将呼叫转移 mMapView.onCreate(...) 移动到 onViewCreated(...) 因为在 onCreate()mMapView 还没有膨胀。如果你不使用 MapView 那么你应该仔细检查你调用 getMap() 的时刻。我肯定是在内部MapView膨胀之后。

2019 年更新

如果您仍然遇到此问题,请尝试以下操作:

不要扩展 SupportMapFrangemt!

public class MyFragment extends Fragment {

private SupportMapFragment fragment;
private GoogleMap map;

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

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    FragmentManager fm = getChildFragmentManager();
    fragment = (SupportMapFragment) fm.findFragmentById(R.id.map_container);
    if (fragment == null) {
        fragment = SupportMapFragment.newInstance();
        fm.beginTransaction().replace(R.id.map_container, fragment).commit();
    }
}

}

如果您使用 mapView,只需确保您在 mapView.getMapAsync() 之前调用了 mapView.onCreate()。如果您使用的片段和视图仍未初始化,您还可以在 onViewCreated() 方法中调用 mapView.onCreate()