-
Notifications
You must be signed in to change notification settings - Fork 75
Data sources
Starting from version 2.3, SDK supports new data sources interfaces. Data source interfaces can be used to customize layer data handling and are much simpler to implement compared to full custom layers. They hide many internal details compared to custom layers, are more scalable and composable.
A simple working example how data sources can be used instead of specialized layers:
RasterLayer layer = new TMSLayer(new EPSG3857(), 0, 19, layerId, "http://tile.openstreetmap.org/", "/", ".png");
can be replaced with:
RasterDataSource dataSource = new HTTPRasterDataSource(new EPSG3857(), 0, 19, "http://tile.openstreetmap.org/{zoom}/{x}/{y}.png");
RasterLayer layer = new RasterLayer(dataSource, layerId);
Two things to note here: RasterLayer has a constructor that takes RasterDataSource instance as an argument (instead of projection), projection is specified when data source is constructed. Here HTTPRasterDataSource is a generalized implementation that can be used with various tile sets, including TMS and Bing. Actual tile URL generation is based on template URL and tags, details are in javadoc.
RasterDataSource itself is a simple interface:
public interface RasterDataSource {
public interface OnChangeListener {
void onTilesChanged();
}
Projection getProjection();
int getMinZoom();
int getMaxZoom();
TileBitmap loadTile(MapTile tile);
void addOnChangeListener(OnChangeListener listener);
void removeOnChangeListener(OnChangeListener listener);
}
Thus in addition to querying data, raster data sources provide listener interface for monitoring changes. If raster data source signals that its tiles have changed, layer will automatically remove all tiles from caches. This was not supported in previous SDK versions.
In addition to HTTPRasterDataSource, SDK has built in support for caching data source (CacheRasterDataSource) and image filter data source (ImageFilterDataSource). Both are virtual data sources that connect to other data sources for initial or actual data.
For example:
RasterDataSource osmDS = new HTTPRasterDataSource(new EPSG3857(), 0, 19, "http://tile.openstreetmap.org/{zoom}/{x}/{y}.png");
ImageFilterRasterDataSource.ImageFilter imageFilter = new ImageFilterRasterDataSource.ImageFilter() {
@Override
public Bitmap filter(Bitmap bitmap) {
return BitmapUtils.invertBitmap(bitmap);
}
};
RasterDataSource filterDS = new ImageFilterRasterDataSource(osmDS, imageFilter);
RasterLayer layer = new RasterLayer(filterDS, layerId);
Here initial data source is connected to image filter data source that inverts colors of all incoming tiles (actual code for inverting is not shown here). The filtered data source is connected to the layer.
CacheRasterDataSource can be useful if the built-in caching in SDK does not suffice or is not flexible enough. It provides customizable interface for cache management for raster tiles:
interface CacheRasterDataSource.CacheStore {
public interface CacheStore {
void open();
void close();
TileBitmap get(MapTile tile);
void clear();
void put(MapTile tile, TileBitmap tileBitmap);
void remove(MapTile tile);
}
It is up to implementation to this interface to decide caching policy (which data to drop when cache size is exceeded) and storage implementation (file system, native-side memory, sqlite database).
It can work together with built-in SDK caching as SDK caches are used internally as lower level caches and data source is accessed only when data is not available in them. Internal SDK caching can be switched on/off per layer via RasterLayer.setMemoryCaching and RasterLayer.setPersistentCaching.
AdvancedMap project has samples of other virtual data sources, like ImageCombiner.
Notes:
-
data source implementations must be thread safe! Data source can be accessed from multiple threads at the same time and this is done by design - in order to give better scalability.
-
for actual raster data source implementation it is recommended to use AbstractRasterDataSource instead of implementing RasterDataSource interface directly. If AbstractRasterDataSource is used as a base class, then only loadTile method has to be implemented, all other methods are implemented in the base class.
-
By default memory caching is on and persistent caching is off at layer level (SDK also has a top level caching, called 'texture cache' that is always on and can not be controlled at the layer level). Depending on data source type, caching may need to be changed. For example, persistent caching is usually a good fit for online data sources, while for procedurally generated tiles both memory caching and persistent caching could be switched off.
Vector data sources utilize a similar idea and usage pattern to raster data sources. Vector data sources can be connected to existing vector layers, they provide additional elements to the layer, in addition to the local data that is added/removed via layer add/remove methods.
Vector data source interface:
public interface VectorDataSource<T extends VectorElement> {
public interface OnChangeListener {
void onElementChanged(VectorElement element);
void onElementsChanged();
}
Projection getProjection();
Envelope getDataExtent();
Collection<T> loadElements(CullState cullState);
void onElementChanged(VectorElement element);
void addOnChangeListener(OnChangeListener listener);
void removeOnChangeListener(OnChangeListener listener);
}
SDK itself provides two ready-to-use vector data sources: QuadTreeVectorDataSource and UnculledVectorDataSource. The first keeps all vector elements in quad-tree data structure for fast element retrieval (based on visible map envelope), while the second always returns all elements, even when they are invisible from current view point. UnculledVectorDataSource can be useful in special cases when there are few elements that should be rendered without a delay when view parameters are changed (with QuadTreeVectorDataSource there is a small delay before elements become visible when panning, for example).
Examples of vector data sources can be found in AdvancedMap project and include vector element tiling, clustering and simplification. In addition, starting from release 2.3, editable layers are based on a similar design and it is much easier to add editing to custom data.
Notes:
-
data source implementations must be thread safe! Data source can be accessed from multiple threads at the same time and this is done by design - in order to give better scalability.
-
for actual vector data source implementation it is recommended to use AbstractVectorDataSource instead of implementing VectorDataSource interface directly. If AbstractVectorDataSource is used as a base class, then only loadElements method has to be implemented, all other methods are implemented in the base class.
-
currently single vector data source instance can not be connected to multiple layers. This will result in undefined behavior. This limitation may be lifted in the future, though.