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

Posted

技术标签:

【中文标题】MapFragment 在 getMapAsync(this) 方法中导致 NullPointerException【英文标题】:MapFragment causing NullPointerException at getMapAsync(this) method 【发布时间】:2016-04-07 06:45:40 【问题描述】:

我已经实现了一个在运行时添加MapFragment 的活动。 MapFragment xml 具有静态 fragment,我试图在运行时添加。我还发现 Lollipop 在运行时添加地图片段存在一些问题。请检查Issue raised和temporary solution

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

fragment_map.xml

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

<fragment
    android:id="@+id/map"
    android:name="com.google.android.gms.maps.SupportMapFragment"
    android:layout_
    android:layout_
    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();

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

我无法弄清楚为什么我仍然收到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

【问题讨论】:

((SupportMapFragment) getActivity().getSupportFragmentManager().findFragmentById(R.id.map)).getMapAsync(this); 行放入您的onCreateView() 并从fragment_map.xml中删除tools:context="appCreators.bloodfinder.activity.MapsActivity" 我试过了,但没有运气我得到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 有什么解决办法吗?我已经坚持了 2 天了。 我刚刚解决了。看看我的回答,让我知道。 【参考方案1】:

我终于通过观察 SO 中给出的答案为自己解决了这个问题。我比较了我的代码和答案中的代码。在我看来,这个 API 存在一些混淆,而且 Google 的实现非常广泛。我反复抛出这个异常:

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

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

这些是你需要检查的事情:

    确保你拥有这两个(我只有 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_
        android:layout_/>
    

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

这个父片段显然不应该是 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 的回答中看到的那样

试试看,然后告诉我。

【讨论】:

看起来很有希望。我会尽力让你知道 工作链接魅力!我犯的错误是扩展SupportMapFragment 而不是Fragment。更改为Fragment 有效。在我的情况下,其他情况是完美的。非常感谢。【参考方案2】:

在我的情况下,我在片段的 xml 中静态使用原始 MapView。问题是我不得不将呼叫转移mMapView.onCreate(...) 移动到onViewCreated(...),因为onCreate() mMapView 尚未膨胀。如果您不使用MapView,那么您应该仔细检查您调用getMap() 的时间。我必须在内部 MapView 膨胀之后。

【讨论】:

【参考方案3】:

不久前我一直在努力解决类似的问题。 关键是在适当的时候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_
    android:layout_>
    <fragment
        android:id="@+id/locationMap"
        android:layout_above="@+id/locationLabelTextView"
        android:layout_
        android:layout_
        android:name="com.google.android.gms.maps.SupportMapFragment" />
</FrameLayout>

然后,您可以在onViewCreated() 中通知Activity,您的地图片段可以使用了。

希望对你有帮助

【讨论】:

我会检查这个并告诉你! 嘿,我试过了,但我收到了这个错误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。我认为还有其他原因导致了这个问题!它并没有给我确切的路线或问题的原因。我用谷歌搜索了很多,但结果一无所获! 试过这个。同样的问题。那个例外仍然存在。【参考方案4】:

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

【讨论】:

【参考方案5】:

如果您使用 mapView,请确保您在调用 mapView.onCreate() 之前调用了 mapView.getMapAsync()。如果您正在使用片段并且视图仍未初始化,您也可以在onViewCreated() 方法中调用mapView.onCreate()

【讨论】:

以上是关于MapFragment 在 getMapAsync(this) 方法中导致 NullPointerException的主要内容,如果未能解决你的问题,请参考以下文章

java.lang.NullPointerException: MapFragment.getMapAsync(com.google.android.gms.maps.OnMapReadyCallba

将 getMap 替换为 getMapAsync

无法解决 Fragment 中的 getMapAsync

while 循环中的 mapFrag.getMapAsync() 问题

片段中的 getMapAsync()

使用自定义支持片段将 getMap 替换为 getMapAsync