osmdroid地图瓦片只有在缩小地图后才会加载

3

在每次新安装后,我的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。
3个回答

3

我曾经遇到过这个问题。 似乎如果您最初设置的缩放级别>19,则瓷砖将无法正确渲染。

作为解决方法,我将缩放级别设置为19而不是20。 然后用户可以根据自己的喜好进行设置。


2
每次你放大或缩小地图时,OsmDroid都会检查当前地图视图边界内的每个瓦片索引是否有对应的瓦片副本。如果存在副本,则会从瓦片缓存中复制并绘制在地图上。如果不存在,则会从在线地图瓦片数据库下载该瓦片并绘制在地图上。下载的瓦片将保存在瓦片缓存中,以便下一次这些瓦片索引出现在视图边界内时能够快速检索。
但是,这涉及到大量处理每个事件的瓦片模块提供程序对象。它们保存在MapTileModuleProviderBase瓦片模块提供程序数组中,该数组在MapView.setTileProvider()调用中设置。如果不包括地图瓦片下载模块提供程序,则不会从互联网/网络下载任何瓦片;相反,它将从任何附加的瓦片模块提供程序中检索副本:缓存瓦片模块提供程序、资产瓦片模块提供程序、文件归档模块提供程序等等。如果这些瓦片提供程序中的任何一个缺失,那么该瓦片索引的瓦片将无法正确绘制,你将看到一个空的灰色“瓦片”方块。
这些瓦片模块提供程序可能会引用OsmDroid默认配置实例DefaultConfigurationProvider,以控制瓦片过期率、缓存大小等属性。这些属性会影响瓦片绘制性能。
如果你使用OsmDroid特定的瓦片模块提供程序API(MapsForge、GeoPackage、WMS等)来加载在线/离线地图数据库,这可能会改变当前瓦片模块提供程序数组结构,请按以下步骤正确重置为MAPNIK数据库:

//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属性,则必须调用相应的地图视图无效以强制重新绘制。过于频繁地调用无效会对应用程序的性能产生负面影响。


1

已更新:

https://tile.openstreetmap.org/1/0/0.png

这是瓷砖源正在尝试从中提取图像的网址。正如您所看到的,瓦片已经存在。

您是否尝试过使地图失效以强制重新绘制?

map.invalidate()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接