Add layers with code

This topic explains how to programmatically add layers to a map and how to listen to map events and layer events.

Conceptually, a map consists of a series of layers. A layer is a source of data which is either vector based (points, lines or polygons), or raster based (aerial photograph or a basemap). A map is displayed within a JMap component that can be added to the user interface of an application. The map acts like an empty canvas onto which one or more layers are drawn. Layers display in bottom to top order so that subsequent layers render on top of previous layers. Careful map design is therefore needed to ensure that you can see each of the layers in the map.

Each map layer references data stored in a map service, tiled service, geodatabase, raster file, and so on, rather than actually storing the geographic data. The API supports a wide range of layer types: tiled layers, dynamic layers, feature layers, graphics layers, and many others including OpenStreetMap layers and WMS layers. For information on map layer types, see Layer types.

A configuration of layers and services can also be authored and saved in ArcGIS Online in a web map that is accessed via its unique ID. Learn how to display a web map in the tutorial Build a web mapping app.

Add a layer

All of the layers in the API inherit from the class Layer. This means all layer types can be added to the map using the same coding pattern. This is the case whether your layer references data in an online service (such as ArcGISTiledMapServiceLayer or ArcGISDynamicMapServiceLayer) or references data stored locally on the device (such as ArcGISLocalTiledLayer or RasterLayer).

The following code shows how to add any layer to a map:

// instantiate a JMap
JMap jmap = new JMap();
 
// obtain the JMap's layer list
LayerList layers = jMap.getLayers();
 
// create your layer, for example a tiled map service layer
ArcGISTiledMapServiceLayer layer = new ArcGISTiledMapServiceLayer(
   "http://services.arcgisonline.com/ArcGIS/rest...");
 
// add the layer to the layer list
layers.add(layer);
 
// ... create and add other layers
// ... add the JMap to a Swing container for display

The steps to obtain the layer list from the JMap and add the layer to it can be combined, resulting in just one line of code:

// obtain map's layer list and add a layer to it
jMap.getLayers().add(myLayer);

This one line of code adds your layer to the map as the top-most layer (end position of the layer list). Adding your layer to the map's layer list causes the layer to initialize and display over any layers added previously. If it's the first layer added to the map and initialized, it will also set the map's spatial reference and cause a map event to be fired, as discussed below in Listen to map events. You can also be notified when the layer has initialized; see Verify the layer was loaded below for further information.

Add a basemap using MapOptions

To get a map displaying an ArcGIS tiled map service layer or an OpenStreetMap basemap, you can also use an alternate JMap constructor which takes a MapOptions instance as a parameter. The MapOptions class enables you to configure a JMap instance with a particular basemap, as well as an initial zoom level and latitude-longitude coordinate around which to center the map. The following code shows an example using the MapOptions class:

// map options: topographic map, centered at lat-lon 41.9, 12.5 (Rome), zoom level 12
MapOptions mapOptions = new MapOptions(MapType.TOPO, 41.9000, 12.5000, 12);
 
// create the map using MapOptions
map = new JMap(mapOptions);

The result of this code will be a map containing a topographic basemap displaying the city of Rome:

Map with topographic basemap centered on Rome

Whether you've added a basemap layer using the MapOptions pattern or by explicitly creating a tiled layer and adding it to the map's layer list, you'll need to use the layer list to add subsequent layers to the map. MapOptions is a useful shortcut for selecting from common basemaps and setting the map's initial extent.

Verify that the layer was loaded

Layers connect to web services or reference local data. These external data sources don’t respond instantly, so the API does not block the thread on which they were added to a map: they are loaded asynchronously. If you are adding layers on the thread which responds to mouse or keyboard input, this also means your application stays responsive while your layers load. Because of this asynchronous layer loading, you should not assume that a layer successfully loads as soon as you've called map.getLayers().add(layer). For a layer with an online data source, it takes some time to make a connection with the web service and retrieve the information it needs. For a layer referencing local data, it takes some time to read from the data source and display the data. Or perhaps the web server is down, or the referenced data source has been moved, in which case your layer would not load successfully.

By adding a LayerInitializeCompleteListener to your layer, you can be notified when the layer has initialized as well as whether or not it has initialized successfully. Depending on the status of the layer, you can take an appropriate action, such as notifying the user if the layer has thrown an error.

The following code shows how to add a LayerInitializeCompleteListener to your layer and take action when the layer has initialized or errored:

// create a layer, for example a dynamic layer
ArcGISDynamicMapServiceLayer onlineDynamicLayer = new ArcGISDynamicMapServiceLayer(
    "http://sampleserver6.arcgisonline.com/arcgis/rest/services/WorldTimeZones/MapServer");

// add a layer initialize complete listener, shown here using an anonymous inner class
onlineDynamicLayer.addLayerInitializeCompleteListener(new LayerInitializeCompleteListener() {

  @Override
  public void layerInitializeComplete(LayerInitializeCompleteEvent e) {
    if (e.getLayer().getStatus() == LayerStatus.INITIALIZED) {
      // layer has initialized successfully
      // take action such as adding the layer to a control
    } else {
      // layer has not successfully initialized
      // take action such as reporting any error messages
      System.out.println("Error: " + e.getLayer().getInitializationError());
    }
  }
});

// add the layer to the map's layer list, causing the layer to initialize
map.getLayers().add(tiledLayer);

Once the layer is successfully initialized, its content appears on the map, and you can safely access the layer's properties using the layer's getter methods.

Listen to map events

You can listen to map events by adding a MapEventListener to your JMap instance. For example, you can get notified and take action when the map has its spatial reference set by implementing your listener's mapReady method, or listen for map extent changes by implementing the listener's mapExtentChanged method. Add a MapEventListener to your map as shown below:

map.addMapEventListener(new MapEventListener() {
 
  @Override
  public void mapReady(MapEvent event) {
    // action to take when map is ready (map has its spatial reference set)
  }
 
  @Override
  public void mapExtentChanged(MapEvent event) {
    // action to take when the map's extent changes
  }
 
  @Override
  public void mapDispose(MapEvent event) {
    // action to take when map is disposed
  }
});

To override a subset of the methods in the MapEventListener interface, you can use the MapEventListenerAdapter class instead. This way, you only need to override the methods that interest you, rather than all the methods declared by the interface. The following code snippet shows an example of using the adapter class to only override the mapReady event:

map.addMapEventListener(new MapEventListenerAdapter() {
  @Override
  public void mapReady(MapEvent event) {
    // map has a spatial reference now: print it out
    System.out.println("Map spatial reference: " + event.getMap().getSpatialReference());
  }
});

Listen to layer list events

As discussed previously, programmatically adding layers to a map is done through the intermediary of the map's layer list. In some cases, however, you can have layers automatically added to the map's layer list by certain API method calls. This is the case if you are loading a web map into a JMap: the process of loading the web map's layers for display is automatically handled by the API. In these cases, you can keep track of what layers are being added and removed from a map's layer list using a LayerListEventListener.

The following code snippet shows how to add an anonymous LayerListEventListener instance to a map's LayerList:

map.getLayers().addLayerListEventListener(new LayerListEventListener() {
      
  @Override
  public void multipleLayersRemoved(LayerEvent event) {
    
  }
 
  @Override
  public void multipleLayersAdded(LayerEvent event) {
  
  }

  @Override
  public void layerRemoved(LayerEvent event) {
  
  }
  
  @Override
  public void layerMoved(LayerEvent event) {
  
  }
  
  @Override
  public void layerAdded(LayerEvent event) {
  
  }
});

Implement any of the methods tagged above with @Override according to those events that interest you. To keep track of any layers being added to the layer list (and thus, to the associated map), it is recommended that you implement both the layerAdded and multipleLayersAdded methods. Similarly, it is best to implement both layerRemoved and multipleLayersRemoved to keep track of any layers being removed from the layer list.

As with the MapEventListener interface, you can use an adapter class if you only want to implement a subset of the methods declared by the LayerListEventListener interface. The following is an example of using the adapter class LayerListEventListenerAdapter and overriding the two methods to keep track of any layers being added:

map.getLayers().addLayerListEventListener(new LayerListEventListenerAdapter() {

  @Override
  public void multipleLayersAdded(LayerEvent event) {
    for (Layer layer : event.getChangedLayers().values()) {
      // do something with the layer, for example add it to a control
    }
  }
      
  @Override
  public void layerAdded(LayerEvent event) {
    Layer layer = event.getChangedLayer();
    // do something with the layer
  }
});

For information on all the layer types you can add to a map, including performance considerations, see Layer types.