基于ArcGIS .NET实现Xamarin Forms应用离线地图瓦片缓存方案问询
ArcGIS Xamarin Forms 离线瓦片动态缓存实现方案
核心逻辑
基于ArcGIS Runtime SDK for .NET的TileCache和ExportTileCacheTask,实现本地缓存优先加载+动态区域瓦片下载的功能:通过用户绘制的矩形范围确定下载区域,批量拉取指定层级的瓦片到本地沙盒;自定义瓦片图层优先读取本地缓存,缺失时再请求在线服务。
分步实现
1. 地图区域选择
使用ArcGIS内置的Draw工具让用户绘制矩形区域,获取地理范围Envelope:
// 初始化矩形绘制工具 var drawTool = new Draw(mapView) { GeometryType = GeometryType.Envelope, Symbol = new SimpleFillSymbol(SimpleFillSymbolStyle.Null, Colors.Transparent, new SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Colors.Blue, 2)) }; // 绘制完成触发下载 drawTool.DrawComplete += async (sender, args) => { var downloadExtent = args.Geometry as Envelope; // 替换为你需要的层级范围 await DownloadOfflineTiles(downloadExtent, minZoomLevel: 10, maxZoomLevel: 16); }; // 启动绘制 await drawTool.StartAsync();
2. 批量下载瓦片到本地
通过ExportTileCacheTask创建下载任务,将瓦片保存到移动端沙盒路径:
private async Task DownloadOfflineTiles(Envelope extent, int minZoomLevel, int maxZoomLevel) { var onlineTileServiceUrl = "https://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer"; var exportTask = await ExportTileCacheTask.CreateAsync(new Uri(onlineTileServiceUrl)); // 配置下载参数:范围、层级、缓存格式 var exportParams = new ExportTileCacheParameters(extent, minZoomLevel, maxZoomLevel) { TileFormat = ExportTileCacheTileFormat.Png }; // 本地缓存路径(跨平台适配) var localCachePath = Path.Combine(FileSystem.AppDataDirectory, "OfflineMapCache.tpkx"); // 执行下载任务 var downloadJob = exportTask.ExportTileCache(exportParams, localCachePath); // 可选:监听进度更新UI downloadJob.ProgressChanged += (s, e) => { MainThread.BeginInvokeOnMainThread(() => { progressBar.Progress = e.Progress / 100.0; }); }; await downloadJob.StartAsync(); if (downloadJob.Status == JobStatus.Succeeded) { // 加载本地缓存图层 SwitchToLocalFirstLayer(localCachePath, onlineTileServiceUrl); } }
3. 自定义本地优先瓦片图层
继承ArcGISTiledLayer,重写瓦片请求逻辑,优先读取本地缓存:
public class LocalFirstTiledLayer : ArcGISTiledLayer { private readonly TileCache _localTileCache; private readonly ArcGISTiledLayer _onlineBackupLayer; public LocalFirstTiledLayer(string localCachePath, string onlineServiceUrl) { _localTileCache = new TileCache(localCachePath); _onlineBackupLayer = new ArcGISTiledLayer(new Uri(onlineServiceUrl)); InitializeLayer(); } private async void InitializeLayer() { try { // 先尝试加载本地缓存 var localLayer = new ArcGISTiledLayer(_localTileCache); await localLayer.LoadAsync(); if (localLayer.LoadStatus == LoadStatus.Loaded) { Source = localLayer.Source; return; } } catch { } // 本地缓存失效则加载在线图层 await _onlineBackupLayer.LoadAsync(); Source = _onlineBackupLayer.Source; } // 重写瓦片获取逻辑:本地优先 protected override async Task<ImageTile> GetTileAsync(int level, int row, int column, CancellationToken cancellationToken) { // 检查本地是否存在该瓦片 var localTile = await _localTileCache.GetTileAsync(level, row, column, cancellationToken); if (localTile != null) { return localTile; } // 本地无瓦片时请求在线 return await _onlineBackupLayer.GetTileAsync(level, row, column, cancellationToken); } }
4. 切换到本地优先图层
将自定义图层设置为地图底图:
private void SwitchToLocalFirstLayer(string cachePath, string onlineUrl) { var localFirstLayer = new LocalFirstTiledLayer(cachePath, onlineUrl); mapView.Map = new Map(Basemap.Create(localFirstLayer)); }
关键注意事项
- SDK版本要求:使用ArcGIS Runtime SDK for .NET 100.12及以上版本,确保
ExportTileCacheTask支持移动端动态下载 - 缓存格式:推荐使用
.tpkx格式(紧凑瓦片包),比传统.tpk占用更少存储空间 - 权限配置:Android需添加
INTERNET、WRITE_EXTERNAL_STORAGE权限;iOS需开启文件访问权限 - 性能优化:下载前可检查本地缓存是否已存在对应区域瓦片,避免重复下载
内容的提问来源于stack exchange,提问作者JoeTaicoon
相关产品推荐
相关产品推荐

