[英]osmdroid map tiles only load after zooming out
在我的MapView
中每次全新安装磁贴后,仅在缩小相当多后才会加载。 之后它工作正常,但我无法弄清楚是什么原因造成的。 调试日志如下:
D/OsmDroid: SqlCache - Tile doesn't exist: Mapnik/1/0/0
D/OsmDroid: Archives - Tile doesn't exist: /1/0/0
D/OsmDroid: SqlCache - Tile doesn't exist: Mapnik/3/1/3
D/OsmDroid: Archives - Tile doesn't exist: /3/1/3
D/OsmDroid: SqlCache - Tile doesn't exist: Mapnik/5/5/12
...
我已经在onViewCreated
中初始化了我的 MapView,如下所示:
map = requireView().findViewById(R.id.map);
map.setTileSource(TileSourceFactory.MAPNIK);
map.getZoomController().setVisibility(CustomZoomButtonsController.Visibility.NEVER);
map.setMultiTouchControls(true);
一旦我获得了位置修复,就会执行以下操作:
IMapController mapController = map.getController();
mapController.setZoom(10.0);
GeoPoint startingPoint = new GeoPoint(location.getLatitude(), location.getLongitude());
mapController.setCenter(startingPoint);
我已经按照 osmdroid 教程,设置了用户代理,向清单添加了必要的权限等等。 如果您需要更多信息,请告诉我。
编辑:我使用的是 6.1.11 版
更新:
https://tile.openstreetmap.org/1/0/0.png
这将是 tilesource 试图从中提取图像的 url。 正如你所看到的那样,瓷砖就在那里。
您是否尝试过使 map 无效以强制重绘?
map.invalidate()
我有这个确切的问题。 似乎如果您最初设置的任何缩放级别 > 19,瓷砖都不会正确渲染。
作为一种解决方法,我将缩放级别设置为 19 而不是 20。然后用户可以根据自己的喜好进行设置
每次放大/缩小时,OsmDroid 都会检查 map 视图当前边界内的每个图块索引是否存在图块副本。 如果存在副本,将从切片缓存中复制并绘制在 map 上。 如果没有,将从在线 map 瓷砖数据库下载瓷砖并在 map 上绘制。 下载的切片将保存在切片缓存中,以便下次这些切片索引位于视图边界中时快速检索。
但是,它确实涉及处理每个事件的大量 tile 模块提供程序对象。 它们保存在MapView.setTileProvider()
调用中设置的MapTileModuleProviderBase
切片模块提供程序数组中。 如果不包括 map 瓦片下载模块提供程序,则不会从 Internet/网络下载任何瓦片; 相反,它将从任何附加的 tile 模块提供程序中检索副本:缓存 tile 模块提供程序、资产 tile 模块提供程序、文件存档模块提供程序等。 如果切片模块提供程序数组中缺少任何这些切片提供程序,则该切片索引的切片将无法正确绘制,您将看到一个空的灰色“切片”方块。
这些 tile 模块提供程序可以参考 OsmDroid 默认配置实例DefaultConfigurationProvider
,用于控制 tile 过期率、缓存大小等的属性。 这些属性会影响瓷砖绘制性能。
如果您使用 OsmDroid 特定的 tile 模块提供程序 API(MapsForge、GeoPackage、WMS 等)来加载在线/离线 map 数据库,这可能会更改当前的 tile 模块提供程序数组结构,请按照以下步骤正确重置到 MAPNK 数据库:
//load MAPNIK basemap updateable from Internet and cacheable
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 的属性,则必须调用相应的 map 视图失效以强制重绘。 过于频繁地调用失效会对应用程序的性能产生负面影响。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.