MapFragment在getMapAsync(this)方法中引起NullPointerException错误。

10

我实现了一个在运行时添加MapFragment的活动。 MapFragment xml具有静态的fragment,我正在尝试在运行时添加。此外,我发现在Lollipop中添加地图片段时存在一些问题。请检查提出的问题临时解决方案

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

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);
}

这总是返回null,我也尝试过其他方法,

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

这也会返回NullPointerException

MapsActivity.java

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

我将这段代码添加到Activity回调的onCreate方法中。

我无法弄清楚为什么我仍然会得到NullPointerException错误!

有时我会得到尝试在空对象引用上调用接口方法'void com.google.maps.api.android.lib6.e.fl.o()'的错误。

希望能得到帮助!

更新:问题仍未解决,我收到以下错误。我查看了日志,但不知道为什么会发生这种情况。

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

((SupportMapFragment) getActivity().getSupportFragmentManager().findFragmentById(R.id.map)).getMapAsync(this);这行代码放在你的onCreateView()方法中。 - Pankaj
fragment_map.xml 中删除 tools:context="appCreators.bloodfinder.activity.MapsActivity" - Pankaj
我尝试了但没有运气,我得到了无法恢复活动{MapsActivity}:java.lang.NullPointerException: 尝试在空对象引用上调用接口方法'void com.google.maps.api.android.lib6.e.fl.o()' - Kavin Prabhu
有解决方案了吗?我已经被这个问题困扰了两天了。 - Arnold Balliu
我刚刚解决了它。看看我的答案,然后告诉我。 - Arnold Balliu
5个回答

16

通过观察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
        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" />
  • 您有一个XML片段,其中类属性如下所示是正确的

  •    <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的答案中看到的那样。

    试一试,然后告诉我。


    看起来很有前途。我会尝试并告诉你。 - Kavin Prabhu
    运行得很好!我犯的错误是扩展SupportMapFragment而不是Fragment。改为使用Fragment就可以了。在我的情况下,其他方案都很完美。非常感谢。 - Kavin Prabhu

    4
    在我的情况下,我在一个片段的xml中静态地使用原始MapView。问题是我不得不将调用转发mMapView.onCreate(...)移动到onViewCreated(...),因为在onCreate()mMapView尚未被填充。如果您不使用MapView,则应该仔细检查何时调用getMap()。必须在内部MapView填充后调用它。

    2
    如果您使用mapView,请确保在调用mapView.getMapAsync()之前调用mapView.onCreate()。如果您正在使用片段并且视图尚未初始化,则还可以在onViewCreated()方法中调用mapView.onCreate()。请注意保留HTML标记。

    2

    我之前也遇到了类似的问题。 关键在于在FragmentonViewCreated()方法中,在合适的时机调用getMap()

    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,您的地图片段已准备好使用。
    希望这有所帮助。

    我会检查这个并让你知道! - Kavin Prabhu
    1
    嘿,我尝试了,但是收到了这个错误 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。我认为还有其他原因导致了这个问题!而且它没有给我确定的行或者问题的原因。我已经谷歌搜索过很多次但都没有结果! - Kavin Prabhu
    1
    尝试过了,问题依旧存在。那个异常还在。 - Arnold Balliu

    2

    2019更新

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

    不要扩展SupportMapFragment!

    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();
        }
    }
    

    }


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接