1.osmdroid加载第三方地图的方式
第一种:通过拓展图源的方式
第二种:通过包装(如对google地图的api进行包装),用统一的接口进行调用。
2.osmdroid-third-party源码介绍
osmdroid提供了加载第三方地图的扩展,主要通过学习其源码,学会使用osmdroid提供的接口实现加载第三方地图,但更重要的是学习其中的思想。
在osmdroid源码中实现的module是osmdroid-third-party,先看一下结构:
api定义了一些接口和自己的实现类
google中通过第二种方式定义了overlay和wrapper包装类
bing中通过第一种方式加载bing地图
3.google的包装设计
先看几个样类:
GeoPoint类
public class GeoPoint implements IGeoPoint { private final com.google.android.maps.GeoPoint mGeoPoint; public GeoPoint(final com.google.android.maps.GeoPoint pGeoPoint) { mGeoPoint = pGeoPoint; }MapController
public class MapController implements IMapController { private final com.google.android.maps.MapController mController; public MapController(final com.google.android.maps.MapController pController) { mController = pController; }MapViewpublic class MapView implements IMapView { private final com.google.android.maps.MapView mMapView; public MapView(final com.google.android.maps.MapView pMapView) { mMapView = pMapView; }MapWrapper实现IMap接口并使用持有的googlemap实现对应的地图操作
class MapWrapper implements IMap { private GoogleMap mGoogleMap; private HashMap<Integer, com.google.android.gms.maps.model.Polyline> mPolylines; private static final Random random = new Random(); MapWrapper(final GoogleMap aGoogleMap) { mGoogleMap = aGoogleMap; } @Override public float getZoomLevel() { final CameraPosition cameraPosition = mGoogleMap.getCameraPosition(); return cameraPosition.zoom; }
我们可以很明显看出来这几个类的特点,都是自定义了一个类,然后都持有google对应的类,具体的实现是通过google的api实现的,但是调用的时候却是调用的自己定义的接口,比如调用的时候,简单来讲就是调用依赖抽象,不依赖具体的实现(这句话真的是真理)。
IMap mMap = MapFactory.getMap(mMapViewV2); final Position position = new Position(52.370816, 9.735936); // Hannover position.setZoomLevel(14); mMap.setPosition(position); mMap.setMyLocationEnabled(false);MapFactory.getMap的源码mMap.setOnCameraChangeListener(new OnCameraChangeListener() { @Override public void onCameraChange(final IPosition position) { Log.d(Constants.LOGTAG, "onCameraChange"); } });public static IMap getMap(final com.google.android.gms.maps.MapView aMapView) { final GoogleMap map = aMapView.getMap(); MapsInitializer.initialize(aMapView.getContext()); return map != null ? new MapWrapper(map) : null; }其中IMap是api包中定义的接口,其中定义了很多地图有关操作的接口,比如放大缩小,设置中心点,边界,监听等等,iMap的源码如下,public interface IMap { float getZoomLevel(); void setZoom(float zoomLevel); IGeoPoint getCenter(); void setCenter(double latitude, double longitude); float getBearing(); void setBearing(float bearing); void setPosition(IPosition position); boolean zoomIn(); boolean zoomOut(); void setMyLocationEnabled(boolean enabled); boolean isMyLocationEnabled(); IProjection getProjection(); void addMarker(Marker marker); int addPolyline(Polyline polyline); void addPointsToPolyline(int id, IGeoPoint... points); void clearPolyline(int id); void clear(); void setOnCameraChangeListener(OnCameraChangeListener listener); }问题来了,这么费劲的要自定义这么多的类到底有什么好处!!!不能只出活不讨好吧。其实这应用了一种设计模式--装饰设计,没了解过的可以看一下我的另一篇博客http://blog.csdn.net/qq_30124547/article/details/53184754很简单的一个例子,但是基本上可以理解了。
现在,突然google地图不能用了,我们需要换成bing地图,也就是微软的地图,该怎么办,我们只需要写一个BingWrapper继承IMap并实现对应的地图操作即可,实际调用的地方改动的地方很小,以前总是不注重设计模式,但是自从知道它的好之后,就再也停不下来了,其实还有一种代理模式跟装饰设计很想——代理模式,虽然很像,但还是有区别的。
注意:要想用谷歌的api,必须用注册一个api-key的东西,需要包名+签名文件的sha1值生成,而且更换签名、包名、电脑、、、、key都将不能使用,需要重新生成,详细的还是看官方的中文指南。点我穿越
还有要注意一点的就是,在国内使用google地图需要翻墙才能显示。不然只会显示网格,没有地图数据。
4.拓展图源的方式加载bing地图
拓展图源的方式相对来说比包装的形式更方便快捷,但是同时也会有很多的问题
官方给的示例是使用bing地图的图源
public class BingMapTileSource extends QuadTreeTileSource implements IStyledTileSource<String>实现方式是继承QuadTreeTileSource,实现IStyledTileSource<String>接口,实现对应的方法即可,其中比较重要的就是瓦片源地址
// URL used to get imageryData. It is requested in order to get tiles url patterns private static final String BASE_URL_PATTERN = "http://dev.virtualearth.net/REST/V1/Imagery/Metadata/%s?mapVersion=v1&output=json&key=%s";具体便不再详细介绍,具体调用就很简单:
BingMapTileSource source = new BingMapTileSource(null); mMapView.setTileSource(source);然后所有逻辑都是osmdroid自身的逻辑相同。