diff --git a/app/src/main/java/com/mapbox/mapboxsdk/plugins/testapp/activity/traffic/TrafficActivity.kt b/app/src/main/java/com/mapbox/mapboxsdk/plugins/testapp/activity/traffic/TrafficActivity.kt index 0f767a2be..95fa1bcc7 100644 --- a/app/src/main/java/com/mapbox/mapboxsdk/plugins/testapp/activity/traffic/TrafficActivity.kt +++ b/app/src/main/java/com/mapbox/mapboxsdk/plugins/testapp/activity/traffic/TrafficActivity.kt @@ -42,7 +42,7 @@ class TrafficActivity : AppCompatActivity(), OnMapReadyCallback { override fun onMapReady(mapboxMap: MapboxMap) { this.mapboxMap = mapboxMap mapboxMap.setStyle(Style.MAPBOX_STREETS) { - this.trafficPlugin = TrafficPlugin(mapView, mapboxMap) + this.trafficPlugin = TrafficPlugin(mapView, mapboxMap, it) this.trafficPlugin?.setVisibility(true) // Enable the traffic view by default } } diff --git a/plugin-traffic/src/main/java/com/mapbox/mapboxsdk/plugins/traffic/TrafficPlugin.java b/plugin-traffic/src/main/java/com/mapbox/mapboxsdk/plugins/traffic/TrafficPlugin.java index 4f229472f..e4ed58813 100644 --- a/plugin-traffic/src/main/java/com/mapbox/mapboxsdk/plugins/traffic/TrafficPlugin.java +++ b/plugin-traffic/src/main/java/com/mapbox/mapboxsdk/plugins/traffic/TrafficPlugin.java @@ -4,7 +4,9 @@ import android.support.annotation.ColorInt; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.annotation.UiThread; import android.support.annotation.VisibleForTesting; + import com.mapbox.mapboxsdk.maps.MapView; import com.mapbox.mapboxsdk.maps.MapboxMap; import com.mapbox.mapboxsdk.maps.Style; @@ -15,25 +17,26 @@ import com.mapbox.mapboxsdk.style.layers.SymbolLayer; import com.mapbox.mapboxsdk.style.sources.Source; import com.mapbox.mapboxsdk.style.sources.VectorSource; -import timber.log.Timber; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; -import static com.mapbox.mapboxsdk.style.expressions.Expression.interpolate; +import timber.log.Timber; + import static com.mapbox.mapboxsdk.style.expressions.Expression.exponential; -import static com.mapbox.mapboxsdk.style.expressions.Expression.match; import static com.mapbox.mapboxsdk.style.expressions.Expression.get; +import static com.mapbox.mapboxsdk.style.expressions.Expression.interpolate; import static com.mapbox.mapboxsdk.style.expressions.Expression.literal; +import static com.mapbox.mapboxsdk.style.expressions.Expression.match; import static com.mapbox.mapboxsdk.style.expressions.Expression.stop; import static com.mapbox.mapboxsdk.style.expressions.Expression.zoom; -import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineColor; -import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineOffset; -import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineWidth; import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineCap; +import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineColor; import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineJoin; +import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineOffset; import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineOpacity; +import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineWidth; import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.visibility; /** @@ -47,9 +50,11 @@ * Use {@link #isVisible()} to validate if the plugin is active or not. *

*/ +@UiThread public final class TrafficPlugin { private final MapboxMap mapboxMap; + private Style style; private final List layerIds = new ArrayList<>(); private final String belowLayer; private boolean visible; @@ -60,8 +65,8 @@ public final class TrafficPlugin { * @param mapView the MapView to apply the traffic plugin to * @param mapboxMap the MapboxMap to apply traffic plugin with */ - public TrafficPlugin(@NonNull MapView mapView, @NonNull MapboxMap mapboxMap) { - this(mapView, mapboxMap, null); + public TrafficPlugin(@NonNull MapView mapView, @NonNull MapboxMap mapboxMap, @NonNull Style style) { + this(mapView, mapboxMap, style, null); } /** @@ -71,12 +76,16 @@ public TrafficPlugin(@NonNull MapView mapView, @NonNull MapboxMap mapboxMap) { * @param mapboxMap the MapboxMap to apply traffic plugin with * @param belowLayer the layer id where you'd like the traffic to display below */ - public TrafficPlugin(@NonNull MapView mapView, @NonNull MapboxMap mapboxMap, + public TrafficPlugin(@NonNull MapView mapView, @NonNull MapboxMap mapboxMap, @NonNull Style style, @Nullable String belowLayer) { + if (!style.isFullyLoaded()) { + throw new RuntimeException("The style has to be non-null and fully loaded."); + } + this.mapboxMap = mapboxMap; + this.style = style; this.belowLayer = belowLayer; - mapView.addOnDidFinishLoadingStyleListener(new StyleLoadHandler(this)); - updateState(); + mapView.addOnWillStartLoadingMapListener(new StyleLoadHandler(this)); } /** @@ -94,13 +103,19 @@ public boolean isVisible() { * @param visible true for visible, false for none */ public void setVisibility(boolean visible) { - Source source = mapboxMap.getStyle().getSource(TrafficData.SOURCE_ID); + this.visible = visible; + + if (!style.isFullyLoaded()) { + // We are in progress of loading a new style + return; + } + + Source source = style.getSource(TrafficData.SOURCE_ID); if (source == null) { initialise(); } - this.visible = visible; - List layers = mapboxMap.getStyle().getLayers(); + List layers = style.getLayers(); for (Layer layer : layers) { if (layerIds.contains(layer.getId())) { layer.setProperties(visibility(visible ? Property.VISIBLE : Property.NONE)); @@ -108,18 +123,6 @@ public void setVisibility(boolean visible) { } } - /** - * Update the state of the traffic plugin. - */ - private void updateState() { - Source source = mapboxMap.getStyle().getSource(TrafficData.SOURCE_ID); - if (source == null) { - initialise(); - return; - } - setVisibility(visible); - } - /** * Initialise the traffic source and layers. */ @@ -139,7 +142,7 @@ private void initialise() { */ private void addTrafficSource() { VectorSource trafficSource = new VectorSource(TrafficData.SOURCE_ID, TrafficData.SOURCE_URL); - mapboxMap.getStyle().addSource(trafficSource); + style.addSource(trafficSource); } /** @@ -185,7 +188,7 @@ private void addLocalLayer() { */ private String placeLayerBelow() { if (belowLayer == null || belowLayer.isEmpty()) { - List styleLayers = mapboxMap.getStyle().getLayers(); + List styleLayers = style.getLayers(); Layer layer; for (int i = styleLayers.size() - 1; i >= 0; i--) { layer = styleLayers.get(i); @@ -315,8 +318,8 @@ private String getLastAddedLayerId() { * @param idAboveLayer the id of the layer above */ private void addTrafficLayersToMap(Layer layerCase, Layer layer, String idAboveLayer) { - mapboxMap.getStyle().addLayerBelow(layerCase, idAboveLayer); - mapboxMap.getStyle().addLayerAbove(layer, layerCase.getId()); + style.addLayerBelow(layerCase, idAboveLayer); + style.addLayerAbove(layer, layerCase.getId()); layerIds.add(layerCase.getId()); layerIds.add(layer.getId()); } @@ -549,7 +552,7 @@ private static class TrafficColor { static final int CASE_RED = Color.parseColor("#5f1117"); } - private static class StyleLoadHandler implements MapView.OnDidFinishLoadingStyleListener { + private static class StyleLoadHandler implements MapView.OnWillStartLoadingMapListener { private WeakReference trafficPlugin; @@ -558,11 +561,21 @@ private static class StyleLoadHandler implements MapView.OnDidFinishLoadingStyle } @Override - public void onDidFinishLoadingStyle() { + public void onWillStartLoadingMap() { TrafficPlugin trafficPlugin = this.trafficPlugin.get(); - if (trafficPlugin != null && trafficPlugin.isVisible()) { - trafficPlugin.updateState(); + if (trafficPlugin != null) { + trafficPlugin.onWillStartLoadingMap(); } } } + + private void onWillStartLoadingMap() { + mapboxMap.getStyle(new Style.OnStyleLoaded() { + @Override + public void onStyleLoaded(@NonNull Style style) { + TrafficPlugin.this.style = style; + setVisibility(visible); + } + }); + } } diff --git a/plugin-traffic/src/test/java/com/mapbox/mapboxsdk/plugins/traffic/TrafficPluginTest.java b/plugin-traffic/src/test/java/com/mapbox/mapboxsdk/plugins/traffic/TrafficPluginTest.java index e90e7f972..4507db215 100644 --- a/plugin-traffic/src/test/java/com/mapbox/mapboxsdk/plugins/traffic/TrafficPluginTest.java +++ b/plugin-traffic/src/test/java/com/mapbox/mapboxsdk/plugins/traffic/TrafficPluginTest.java @@ -2,10 +2,12 @@ import com.mapbox.mapboxsdk.maps.MapView; import com.mapbox.mapboxsdk.maps.MapboxMap; +import com.mapbox.mapboxsdk.maps.Style; import org.junit.Rule; import org.junit.Test; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; @@ -15,29 +17,40 @@ public class TrafficPluginTest { @Mock - MapView mapView; + private MapView mapView; @Mock - MapboxMap mapboxMap; + private MapboxMap mapboxMap; + + @Mock + private Style style; @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); - @Test(expected = NullPointerException.class) + @Test(expected = RuntimeException.class) public void testNonNullAnnotatedArgs() { - new TrafficPlugin(null, null); + new TrafficPlugin(null, null, null); } @Test public void testSanity() { - new TrafficPlugin(mapView, mapboxMap); + Mockito.when(style.isFullyLoaded()).thenReturn(true); + new TrafficPlugin(mapView, mapboxMap, style); } @Test public void testToggle() { - TrafficPlugin trafficPlugin = new TrafficPlugin(mapView, mapboxMap); + Mockito.when(style.isFullyLoaded()).thenReturn(true); + TrafficPlugin trafficPlugin = new TrafficPlugin(mapView, mapboxMap, style); assertFalse(trafficPlugin.isVisible()); trafficPlugin.setVisibility(true); assertTrue(trafficPlugin.isVisible()); } + + @Test(expected = RuntimeException.class) + public void testNotLoadedStyle() { + Mockito.when(style.isFullyLoaded()).thenReturn(false); + new TrafficPlugin(mapView, mapboxMap, style); + } }