Precaching API For Offline Maps
Last year, we published a post on Best Practices for Offline Maps. Since then, our 14.3 release has introduced a new API for pre-caching map tiles for offline use.
In today’s post, we’ll walk through how this new Pre-Caching API works and how you can use it in your applications to streamline offline map access. Be sure to revisit our earlier offline mapping post as well - it covers a broader range of strategies beyond the specific tile caching that we’ll explore here.
Tip
To see the Precaching API in action, just clone the HowDoI samples, run the solution and then click on the ‘Pre-Generate Cache for XYZ Layers’ under the ‘XYZ Layers’ section of the samples, and also the 'Pre-Generate Cache for Tile Overlay' sample under the 'Miscellaneous' section.
Overview of Tile Caching
Image 1: ‘HowDoI' Sample showing the Precaching API in action.
Tile caching is the process of storing map tiles - small square images that make up a map - so they don’t have to be downloaded from a server every time a user views the map. By caching these tiles locally (on disk or in memory), you can greatly improve performance, reduce bandwidth usage, and support offline map access when there's no internet connection.
In the ‘HowDoI’ sample shown in Image 1, users can click the ‘Generate Cache’ button to programmatically pre-cache a selected area of the map. The sample also overlays red grid lines and labels to visually indicate tile boundaries and whether each tile was loaded from the cache or fetched live.
Additional buttons let users clear the cache or open the cache directory on disk. This makes it easy for developers to explore the full functionality of the new pre-caching API and observe how the map behaves under different conditions.
Overlays vs. Layers
Before we dive into code examples, it’s important to know the difference between Overlays and Layers in ThinkGeo. A Layer typically represents a single source of data—for example, restaurants, roads, or building footprints. Layers are defined in ThinkGeo.Core.dll
and are available across all platforms: Desktop, Mobile, and Web.
An Overlay is a container that holds one or more layers. While the concept is consistent across platforms, the implementation can vary slightly. For instance, LayerOverlay
behaves a bit differently in Desktop applications compared to MAUI. Check out this article to learn more about ThinkGeo Overlays and Layers.
The new caching API has been implemented in 2 places:
RasterXyzTileAsyncLayer layers (on all platforms) - All layer that inherit from the RasterXyzTileAsyncLayer now have access to the pre-caching api. A few of the more popular classes that you can now easily cache include:
OpenStreetMaps
WMTS services
Popular premium providers such as Mapbox, Bing and Here maps.
Raster MbTiles
Most other standard XYZ servers
and many more.
LayerOverlay (in desktop only) - If you’re working in WPF or Winforms, the LayerOverlay can also be easily cached using the new API. When the LayerOverlay tiles are cached, all Layers in the overlay (both vector or raster) will be cached in the overlay tile cache.
Keep in mind these differences between Layers and Overlays when we start to dig into the code below.
Code Examples
Probably the most important method in the new caching API is GenerateTileCacheAsync. This method is available on both the RasterXyzTileAsyncLayer and the LayerOverlay. This method takes a bounding box as a parameter for the area you want to cache, and also has parameters for the zoomlevels and/or scales that you want to cache. Here’s an example of using the GenerateTileCacheAsync method on both a LayerOverlay and OpenStreetMapAsyncLayer:
// add an event handler that we'll look at in the next section.
_layerOverlay.TileCacheGenerated += OpenStreetMapAsyncLayerOnTileCacheGenerated;
// Using the LayerOverlay, generate the cache for the current and the next 3 zooms.
var zoom = _layerOverlay.TileMatrixSet.GetSnappedZoomIndex(MapView.CurrentScale);
await _layerOverlay.GenerateTileCacheAsync(_bbox, zoom, zoom + 3, scaleFactor);
// Using the OpenStreetMapAsyncLayer, generate a tile cache for a given bounding box and zoomlevels 0-4
var northAmericaExtent = new RectangleShape(-20030000, 20030000, 0, 0);
await _openStreetMapAsyncLayer.GenerateTileCacheAsync(northAmericaExtent, 0, 4);
While the GenerateTileCacheAsync is the most important new method, let’s also review some other events and properties in the new API. Because tile caches can take a while to build (especially if you’re fetching the data from a web service), the OnTileCacheGenerated event is useful to track the progress of your cache build. In the code sample below, this event is used to update a progress bar at the bottom of the samples:
private void OpenStreetMapAsyncLayerOnTileCacheGenerated(object sender, TileCacheGeneratedXyzTileAsyncLayerEventArgs e)
{
Dispatcher.Invoke(() =>
{
_finishedTileCount++;
MyProgressBar.Maximum = e.TotalTileCount;
MyProgressBar.Value = _finishedTileCount;
LblStatus.Content = $"{_finishedTileCount} / {e.TotalTileCount}";
});
}
It’s also worth mentioning that both the RasterXyzTileAsyncLayer and the LayerOverlay classes use the TileCache object. The TileCache has handy properties like the ExpirationTime and TileAccessMode. You can also find some useful helper functions here such as ClearCache() to delete all cached tiles or DeleteTile() to selectively remove a tile from the cache.
Summary
We hope you find this post useful. If you have questions, or if you have a topic you'd like us to explore further, we’d love to hear from you! Email us at sales@thinkgeo.com or schedule a meeting to talk in person. We always enjoy connecting with our customers, learning how you’re using ThinkGeo, and finding new ways to improve our products.
About ThinkGeo
We are a GIS software company founded in 2004 and located in Frisco, TX. Our clients are in more than 40 industries including agriculture, energy, transportation, government, engineering, IT, and defense. We pride ourselves on our excellent service and transparency. ThinkGeo offers a variety of products and services to meet almost any GIS application need. We can even help you develop your next project - anywhere from a few hours of consulting to outsourcing an entire project. To learn more, email us at sales@thinkgeo.com, or call us direct at 1-214-449-0330.