Android Maps V2 MapView内置自定义片段(NPE)

Android Maps V2 MapView内置自定义片段(NPE),android,google-maps,maps,Android,Google Maps,Maps,我不想使用或扩展SupportMapFragment或MapFragment。我有自己的基类,里面有一堆代码 文档明确指出,当某人单独使用MapView时,应调用所有相应的生命周期方法(onCreate()onResume()等) 片段中的大多数生命周期方法类似于活动,但当我在片段之间来回切换时,我最终在onDestroy()或onResume()方法中得到一个模糊的NPE 提供的所有示例都使用带有地图视图的活动,但不是自定义的片段 已经有人这么做了吗?您能否在自己的片段类中提供地图视图的示例代

我不想使用或扩展
SupportMapFragment
MapFragment
。我有自己的基类,里面有一堆代码

文档明确指出,当某人单独使用
MapView
时,应调用所有相应的生命周期方法(
onCreate()
onResume()
等)

片段
中的大多数生命周期方法类似于
活动
,但当我在
片段
之间来回切换时,我最终在
onDestroy()
onResume()
方法中得到一个模糊的NPE

提供的所有示例都使用带有
地图视图的
活动
,但不是自定义的
片段


已经有人这么做了吗?您能否在自己的
片段
类中提供
地图视图
的示例代码?

我成功地将地图视图(v2)包含在自定义片段中,该片段本身嵌入了一个ViewPager中。在我的例子中,MapView包含在片段布局文件中。我不得不调用MapView上的生命周期方法(
onCreate()
从片段中调用
onCreateView()
),并手动调用
MapsInitializer.initialize(context)
,以避免类BitmapDescriptorFactory中出现
NullPointerException
(获取标记的位图)。最后一个技巧很奇怪,我不知道为什么地图系统没有在没有这个调用的情况下正确初始化自己,也许这只是当前版本中的一个bug


就我而言,我在
onResume()
onDestroy()
中没有出现任何
NullPointerException
,我对PoPy的答案有些费劲,但最后我还是解决了,下面是我的想法。这可能有助于其他也会遇到此问题的人:

public class MyMapFragment extends Fragment {

    private MapView mMapView;
    private GoogleMap mMap;
    private Bundle mBundle;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View inflatedView = inflater.inflate(R.layout.map_fragment, container, false);

        try {
            MapsInitializer.initialize(getActivity());
        } catch (GooglePlayServicesNotAvailableException e) {
            // TODO handle this situation
        }

        mMapView = (MapView) inflatedView.findViewById(R.id.map);
        mMapView.onCreate(mBundle);
        setUpMapIfNeeded(inflatedView);

        return inflatedView;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mBundle = savedInstanceState;
    }

    private void setUpMapIfNeeded(View inflatedView) {
        if (mMap == null) {
            mMap = ((MapView) inflatedView.findViewById(R.id.map)).getMap();
            if (mMap != null) {
                setUpMap();
            }
        }
    }

    private void setUpMap() {
        mMap.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker"));
    }

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

    @Override
    public void onPause() {
        super.onPause();
        mMapView.onPause();
    }

    @Override
    public void onDestroy() {
        mMapView.onDestroy();
        super.onDestroy();
    }
}
下面是相应的
res/layout/map\u fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

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


如果布局中只有一个元素(如本例所示),则可以省略
RelativeLayout
(并将xmlns declaration向上移动到新的根元素,在本例中为
com.google.android.gms.maps.MapView
),而使用单独的
MapView

    //at Activity
    @Override
    protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      MapsInitializer.initialize(this);
      mapView.onCreate(savedInstanceState); 
    }
    //or at Fragment
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
                       Bundle savedInstanceState) {

       MapsInitializer.initialize(getActivity());  
       mapView.onCreate(mBundle);
     }
    //along with the following
    @Override
    protected void onResume() {
       super.onResume();
       if (mapView != null)
        mapView.onResume();
      }

    @Override
    protected void onDestroy() {
       super.onDestroy();
       if (mapView != null)
        mapView.onDestroy();
    }

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

下面是官方文档中关于MapsInitializer.initialize(context)的一些详细信息:很明显,我已经有了一个Map对象,但是由于某些原因,仍然会引发异常。当我添加了这个静态丑陋调用时,它最终起作用了。@PoPy我正在尝试和你一样做(即:在viewPager中包含mapView),但是如何保持mapView状态(标记、位置、缩放等)。当我从第1页(带地图)转到第3页并返回到第1页时,我的状态将丢失@塞巴斯蒂安,我暂时还没有试图拯救这个州,很抱歉,我帮不了你this@Sebastien我相信MapView.onSaveInstanceState方法可以解决您遇到的问题。感谢您的解决方案,它帮助了我。但是,您是否在视图寻呼机中使用此选项?因为我对这个解决方案和视图寻呼机有问题。我不知道如何保持地图状态(更多细节见我对PoPy答案的评论)。你能帮我吗?非常有用,谢谢Jens;)@jens thanx对于代码,它适用于我的寻呼机的第一个片段,但是当我滑动到第二个片段时,地图视图什么也没有显示——就像在那个帧中什么都没有一样。仅供参考,片段事务在父片段的
onCreateView
方法中完成。我发现的另一个问题是,我已经为GoogleMap对象实现了
setOnMapClickListener
,但似乎所有的点击都没有得到正确的处理。它得到了一些点击,而不是全部。不知道这里发生了什么。谢谢你的实施。我注意到一个问题。从Backback恢复此地图片段时,地图摄影机位置将丢失。在我当前的实现中,每次在片段实例变量中更改相机位置时,我都使用OnCameraChangeListener来保存相机位置。从backstack恢复片段时,我检查此实例变量,如果它不为null,则将地图摄影机移动到此保存的位置。我必须调用
MapView.onDestroy()
,并清除
fragment.onDestroyView()中的
MapView
引用,否则恢复的片段显示的是空的灰色地图(由于在
Fragment.onCreateView()内部调用
MapView.onCreate()
,所以有点道理)@martyonair:我在哪里两次调用它?我在活动或片段中说过你在哪里使用它。请仔细阅读,然后只downvote@laaptu您在哪里初始化了
地图视图
?@anoniim您可以在
活动
片段
上进行初始化,无论您在哪里使用it@laaptu我的意思是什么方法?不能在设置
setContentView
Fragment
onCreateView