使用SupportMapFragment时,如何知道地图已准备就绪?

时间:2012-12-26 22:52:17

标签: android google-maps google-maps-android-api-2

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?

地图实际上是在手机上显示但是我似乎没有运气来获得添加标记的参考。

更新

我通过构造函数创建SupportMapFragment的原因是因为典型的setContentView崩溃并且无效。这使我陷入困境,在onCreate方法中我无法获得我的参考,因为那时我实际创建了SupportMapFragment。在进一步调查中,我的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
    }

7 个答案:

答案 0 :(得分:35)

编辑:getMap is deprecated now

  

问题是当对getMap的调用为null时,我什么时候可以再试一次?

这取决于问题的性质。

如果您通过布局中的SupportMapFragment元素设置<fragment>,则可以getMap()成功呼叫onCreate()。但是,如果您通过构造函数创建SupportMapFragment,那太快了 - GoogleMap尚不存在。您可以延长SupportMapFragment并覆盖onActivityCreated(),因为getMap()已准备就绪。

但是,getMap() 返回null以解决更大的问题,例如未安装Google Play服务。您需要使用GooglePlayServicesUtil.isGooglePlayServicesAvailable()之类的东西来检测这种情况并按照您的意愿处理它。

答案 1 :(得分:14)

我最终扩展了SupportMapFragment类并使用了回调。代码在这里:

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)方法,但在我的情况下,我不希望回调返回到我的MainActivity。我希望它返回到Fragment的一个实例。 (GoogleMap本质上是一个片段内的片段)我设置回调并以编程方式加载地图。我想在MySupportMapFragment的构造函数中设置itsMapViewCreatedListener,但不鼓励使用除无参数构造函数之外的任何东西。

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...
}

答案 2 :(得分:11)

我会评论CommonsWare的答案,但我没有足够的代表。无论如何,我也有这个问题,getMap()将在onActivityCreated中返回null。我的设置是这样的:我的MainActivity包含一个片段。在该片段的onCreateView方法中,我创建了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;   
}

答案 3 :(得分:7)

上个月(2014年12月)Google为此问题提供了官方解决方案。在newest (6.5) Google Play Services

  

现在不推荐使用MapView和MapFragment中的getMap()方法来支持新的getMapAsync()方法。

使用getMapAsync(OnMapReadyCallback callback),您可以在GoogleMap准备就绪时设置监听器。它在回调中传递,并且它被提供为非null。

Google为此提供了sample code

public class MainActivity extends FragmentActivity
    implements OnMapReadyCallback {
...
}

和初始化片段时:

MapFragment mapFragment = (MapFragment) getFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);

当地图准备好后,您将调用回调

@Override
public void onMapReady(GoogleMap map) {
    map.addMarker(new MarkerOptions()
        .position(new LatLng(0, 0))
        .title("Marker"));
}

答案 4 :(得分:0)

如果问题与未初始化的库有关,也可以使用MapsInitializer.initialize(context);

答案 5 :(得分:0)

使用最新的Google服务,您可以使用MapFragment.getMapAsync。 直接来自文档

  

设置一个回调对象,该对象将在准备好使用GoogleMap实例时触发。

答案 6 :(得分:0)

如果map == null则找到地图

 if (mGoogleMap == null)
    {
        SupportMapFragment mapFragment1 = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);

        mapFragment1.getMapAsync(this);
    }

然后调用你的函数onMapReady();