簡體   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