每次你放大或缩小地图时,OsmDroid都会检查当前地图视图边界内的每个瓦片索引是否有对应的瓦片副本。如果存在副本,则会从瓦片缓存中复制并绘制在地图上。如果不存在,则会从在线地图瓦片数据库下载该瓦片并绘制在地图上。下载的瓦片将保存在瓦片缓存中,以便下一次这些瓦片索引出现在视图边界内时能够快速检索。
但是,这涉及到大量处理每个事件的瓦片模块提供程序对象。它们保存在
MapTileModuleProviderBase
瓦片模块提供程序数组中,该数组在
MapView.setTileProvider()
调用中设置。如果不包括地图瓦片下载模块提供程序,则不会从互联网/网络下载任何瓦片;相反,它将从任何附加的瓦片模块提供程序中检索副本:缓存瓦片模块提供程序、资产瓦片模块提供程序、文件归档模块提供程序等等。如果这些瓦片提供程序中的任何一个缺失,那么该瓦片索引的瓦片将无法正确绘制,你将看到一个空的灰色“瓦片”方块。
这些瓦片模块提供程序可能会引用OsmDroid默认配置实例
DefaultConfigurationProvider
,以控制瓦片过期率、缓存大小等属性。这些属性会影响瓦片绘制性能。
如果你使用OsmDroid特定的瓦片模块提供程序API(MapsForge、GeoPackage、WMS等)来加载在线/离线地图数据库,这可能会改变当前瓦片模块提供程序数组结构,请按以下步骤正确重置为MAPNIK数据库:
IFilesystemCache tileWriter = null;
INetworkAvailablityCheck networkAvailabilityCheck = new NetworkAvailabliltyCheck(getContext());
List<MapTileModuleProviderBase> defaultProviders = new ArrayList<>();
SimpleRegisterReceiver simpleRegisterReceiver = new SimpleRegisterReceiver(getContext());
if (Build.VERSION.SDK_INT < 10) {
tileWriter = new TileWriter();
} else {
tileWriter = new SqlTileWriter();
}
defaultProviders.add(new MapTileAssetsProvider(simpleRegisterReceiver, getContext().getAssets()));
final MapTileAssetsProvider assetsProvider = new MapTileAssetsProvider(
simpleRegisterReceiver, getContext().getAssets(), TileSourceFactory.MAPNIK);
defaultProviders.add(assetsProvider);
final MapTileFileStorageProviderBase cacheProvider =
MapTileProviderBasic.getMapTileFileStorageProviderBase(simpleRegisterReceiver, TileSourceFactory.MAPNIK, tileWriter);
defaultProviders.add(cacheProvider);
final MapTileFileArchiveProvider archiveProvider = new MapTileFileArchiveProvider(
simpleRegisterReceiver, TileSourceFactory.MAPNIK);
defaultProviders.add(archiveProvider);
final MapTileApproximater approximationProvider = new MapTileApproximater();
defaultProviders.add(approximationProvider);
approximationProvider.addProvider(assetsProvider);
approximationProvider.addProvider(cacheProvider);
approximationProvider.addProvider(archiveProvider);
final MapTileDownloader downloaderProvider = new MapTileDownloader(TileSourceFactory.MAPNIK, tileWriter, networkAvailabilityCheck);
defaultProviders.add(downloaderProvider);
MapTileModuleProviderBase[] providerArray = new MapTileModuleProviderBase[defaultProviders.size()];
for (int i = 0; i < defaultProviders.size(); i++) {
providerArray[i] = defaultProviders.get(i);
}
Log.i(IMapView.LOGTAG, String.format("reset MAPNIK: current tile module providers(%d) = %s",
providerArray.length,
Arrays.toString(providerArray)));
MapTileProviderArray obj = new MapTileProviderArray(TileSourceFactory.DEFAULT_TILE_SOURCE, simpleRegisterReceiver, providerArray);
mapView.setTileProvider(obj);
mapView.setTileSource(TileSourceFactory.MAPNIK);
通常情况下,我们不需要显式调用MapView.invalidate()
(如果是从UI线程调用)或MapView.postInvalidate()
(如果是从非UI线程调用),因为这由MapView处理瓷砖资源。
public void setTileProvider(final MapTileProviderBase base) {
this.mTileProvider.detach();
mTileProvider.clearTileCache();
this.mTileProvider = base;
mTileProvider.getTileRequestCompleteHandlers().add(mTileRequestCompleteHandler);
updateTileSizeForDensity(mTileProvider.getTileSource());
this.mMapOverlay = new TilesOverlay(mTileProvider, this.getContext(), horizontalMapRepetitionEnabled, verticalMapRepetitionEnabled);
mOverlayManager.setTilesOverlay(mMapOverlay);
invalidate();
}
如果您在另一个线程中再次更改任何MapView属性,则必须调用相应的地图视图无效以强制重新绘制。过于频繁地调用无效会对应用程序的性能产生负面影响。