如何知道在使用SupportMapFragment时地图已准备好使用?
在onCreate
方法中,我正在使用SupportMapFragment
来显示地图。
SupportMapFragment fragment = new SupportMapFragment(); getSupportFragmentManager().beginTransaction() .add(android.R.id.content, fragment).commit();
结合这一点,我想添加一个标记。 问题是什么时候getMap
的调用是空的,什么时候可以再试一次? 有没有我可以注册的事件,或者我的方法本身是错误的?
mMap = ((SupportMapFragment)(getSupportFragmentManager().findFragmentById(R.id.map))).getMap(); if(mMap == null) //what do I do here?
地图实际上显示在手机上,但是我似乎没有运气来获得添加标记的参考。
更新:
我通过构造函数创buildSupportMapFragment
的原因是典型的setContentView
崩溃,无法正常工作。 这使我陷入了困境,因为我当时实际上正在创buildSupportMapFragment
,所以无法在onCreate
方法中获得我的引用。 在进一步调查中,似乎我的setContentView
问题是没有将Google-play-services jar和module / src设置为整个项目的一部分的副产品。 在做这两个, setContentView
现在的作品,我可以通过getMap()
,我所期望的参考。
lots.xml …
<?xml version="1.0" encoding="utf-8"?> <fragment xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/map" android:name="com.google.android.gms.maps.SupportMapFragment" android:layout_width="match_parent" android:layout_height="match_parent" />
LotsActivity.java …
public class LotsActivity extends FragmentActivity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.lots); GoogleMap mMap; mMap = ((SupportMapFragment)(getSupportFragmentManager().findFragmentById(R.id.map))).getMap(); if(mMap == null) //this should not occur now }
编辑: getMap
现在已经被弃用了
问题是什么时候getMap的调用是空的,什么时候可以再试一次?
这取决于问题的性质。
如果通过布局中的<fragment>
元素设置SupportMapFragment
,则可以在onCreate()
成功调用getMap()
onCreate()
。 但是,如果通过构造函数创buildSupportMapFragment
,那就太快了 – GoogleMap
还不存在。 您可以扩展SupportMapFragment
并覆盖onActivityCreated()
,因为getMap()
已经准备好了。
但是, getMap()
也可以返回null
来解决更大的问题,例如未安装Google Play服务。 您需要使用类似GooglePlayServicesUtil.isGooglePlayServicesAvailable()
来检测这种情况,然后根据需要进行处理。
我最终扩展了SupportMapFragment类并使用callback。 代码在这里:
public class MySupportMapFragment extends SupportMapFragment { public MapViewCreatedListener itsMapViewCreatedListener; // Callback for results public abstract static class MapViewCreatedListener { public abstract void onMapCreated(); } @Override public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = super.onCreateView(inflater, container, savedInstanceState); // Notify the view has been created if( itsMapViewCreatedListener != null ) { itsMapViewCreatedListener.onMapCreated(); } return view; } }
我宁愿使用接口并重写onAttach(activity)方法,但在我的情况下,我不希望callback回到我的MainActivity。 我希望它能够返回到Fragment的一个实例。 (谷歌地图本质上是一个片段内的片段)我设置callback,并以此编程加载地图。 我想在MySupportMapFragment的构造函数中设置它的MapViewCreatedListener,但不鼓励使用除无参数构造函数以外的任何东西。
itsMySupportMapFragment = new MySupportMapFragment(); MapViewCreatedListener mapViewCreatedListener = new MapViewCreatedListener() { @Override public void onMapCreated() { initPlacesGoogleMapCtrl(); } }; itsMySupportMapFragment.itsMapViewCreatedListener = mapViewCreatedListener; FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction(); transaction.replace(R.id.mapFragmentContainer, itsMySupportMapFragment); transaction.addToBackStack(null); transaction.commit();
然后,当我接到电话,我可以得到地图; 没有更多的空!
public void initPlacesGoogleMapCtrl() { // Map ready, get it. GoogleMap googleMap = itsMySupportMapFragment.getMap(); // Do what you want... }
我会评论CommonsWare的答案,但我没有足够的代表。 无论如何,我也有这个问题getMap()将在onActivityCreated返回null。 我的设置是这样的:我有MainActivity包含一个片段。 在该片段的onCreateView方法中,我创build了SupportMapFragment,然后通过childFragmentManager将其添加到片段。 我一直参考SupportMapFragment,并期望它给我onActivityCreated它没有的地图。 解决这个问题的方法是覆盖SupportMapFragment的onActivityCreated而不是父代片段。 我在onCreateView中这样做了:
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.fragment_location, container, false); mMapFragment = new SupportMapFragment() { @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); mMap = mMapFragment.getMap(); if (mMap != null) { setupMap(); } } }; getChildFragmentManager().beginTransaction().add(R.id.framelayout_location_container, mMapFragment).commit(); return v; }
上个月(2014年12月)Google正式解决了这个问题。 最新(6.5)Google Play服务 :
MapView和MapFragment中的getMap()方法现在已被弃用,以支持新的getMapAsync()方法。
使用getMapAsync(OnMapReadyCallback callback)
您可以在GoogleMap准备就绪时设置侦听器。 它在callback中被传递,并且被提供为非空。
Google为此提供了示例代码 :
public class MainActivity extends FragmentActivity implements OnMapReadyCallback { ... }
和初始化片段时:
MapFragment mapFragment = (MapFragment) getFragmentManager().findFragmentById(R.id.map); mapFragment.getMapAsync(this);
当地图准备就绪时,你将会调用callback函数
@Override public void onMapReady(GoogleMap map) { map.addMarker(new MarkerOptions() .position(new LatLng(0, 0)) .title("Marker")); }
你也可以使用MapsInitializer.initialize(context);
如果问题与未初始化的库有关。
使用最新的GoogleServices,您可以使用MapFragment.getMapAsync 。 直接从文档
设置一个callback对象,当准备使用GoogleMap实例时将会触发该对象。
如果map == null,那么find地图
if (mGoogleMap == null) { SupportMapFragment mapFragment1 = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map); mapFragment1.getMapAsync(this); }
然后在MapReady()上调用你的函数。