We are developing an android and iOS App and we would like to improve the performance of the map. In particular the loading speed of the vector tiles that we use.
Our setup is really easy. We have only one layer which is a `ArcGISVectorTiledLayer`. When the map is visible, the data is loaded and displayed. When the map is visible on another screen, the map loads all the data again and the user has to wait.
We would like to cache the vector tile data between maps that are displayed in our apps.
Is that possible?
What other options of caching are available?
@JulianBissekkou You can export the tiles from an online vector tile service or a portal item using the ExportVectorTilesJob .
public ExportVectorTilesJob exportVectorTiles(
ExportVectorTilesParameters exportVectorTilesParameters,
String vectorTileCachePath
)
Check out the Android sample "Export vector tiles" here.
Thanks for reaching out.
I did a quick test and there are a few problems that I found.
When exporting the data I get an error:
"Portal item is missing for style resources. Cannot export an item resource cache."
It might be the case that there are no style ressources. That's a valid state, correct?
Second problem:
I would like to create a vector layer with the cache and the url so that the vector layer can quickly show whats already cached, but if needed it can request new data based on the url.
I don't see a constructor of AGSVectorTiledLayer with url and cache.
Not providing `itemResourceCacheDownloadDirectory` resolved the first issue 🙂
`
Use the available constructor: API ref
ArcGISVectorTiledLayer(java.lang.String dataSourceUri)
It creates a new ArcGISVectorTiledLayer from either the ArcGIS Vector Tile Service, Vector Tile Style Sheet indicated by the given URI, or the path to a Local Vector tile package(VTPK).
I know this constructor but in my case I want to create vector layer that fetches data from remote but also using the existing data it reads from a cache.
To be more specific I want to explain my use case:
In my App I have a few different places where a map is shown. It's mostly centered on the users location, but the user is able to move around the map, zoom in or zoom out.
I don't want the map to always load the tiles again when a new map is created. I would like to keep the data in cache and use it if possible, but if the user decides to move around i want to load new data.
This is currently not possible in a efficient way, or am I wrong? I can download a specific part of a map and create a layer from that data, but my user is not able to scroll somewhere else outside of the downloaded area.
Edit: I know that I can create 2 layers. One with the url and one with the cache, but then we will still load redundant data. I would like to reuse the already fetched data from my vector tiled layer.
Hey @JulianBissekkou, I would like to make sure I'm understanding your problem correctly. You would like to have a local vtpk cache to load a map until the user scrolls outside the cached area, which then map fetches the online URL layer data.
Below is an approach that should help, you might need to tweak according for your app's needs:
// loads the vector tile layer cache.
val vectorTiledLayer = ArcGISVectorTiledLayer(getExternalFilesDir(null)?.path + "/myVectorTiles.vtpk")
vectorTiledLayer.loadAsync()
vectorTiledLayer.addDoneLoadingListener {
// if vector tiles failed to load, show message
if (vectorTiledLayer.loadStatus == LoadStatus.FAILED_TO_LOAD) {
showError(vectorTiledLayer.loadError.message.toString())
}
}
// add the cached tile layer to the map
mapView.map.basemap.baseLayers.add(vectorTiledLayer)
mapView.map.loadAsync()
mapView.addViewpointChangedListener {
// if the map is loaded
if (mapView.map.loadStatus == LoadStatus.LOADED) {
// get the current viewpoint extent
val currentViewpoint = mapView.getCurrentViewpoint(Viewpoint.Type.BOUNDING_GEOMETRY)
// get the cache map's extent
val mapExtent = vectorTiledLayer.fullExtent
// check if the user's viewpoint overlaps the cache map's extent
if (GeometryEngine.overlaps(currentViewpoint.targetGeometry, mapExtent)) {
Log.e(TAG, "Out of bounds")
// load online resource now, since user has panned to the map's bounding extent
// switch to use online basemap, and set the viewpoint as current extent
mapView.map = ArcGISMap(Basemap(BasemapStyle.ARCGIS_STREETS_NIGHT))
mapView.setViewpoint(currentViewpoint)
}
}
}