繁体   English   中英

osmdroid map 磁贴仅在缩小后加载

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM