From d6b38153eb4be17d454f0afa998e1cc920c441ae Mon Sep 17 00:00:00 2001 From: Seth Bourget Date: Thu, 5 Jan 2023 11:40:14 -0800 Subject: [PATCH 1/2] Modified the initialize layers behavior to always apply the current options even if it means removing the existing layers. --- changelog/unreleased/bugfixes/6793.md | 1 + .../route/line/MapboxRouteLineUtils.kt | 27 ++ .../route/line/api/MapboxRouteLineView.kt | 56 +++- .../route/line/MapboxRouteLineUtilsTest.kt | 35 +++ .../route/line/api/MapboxRouteLineViewTest.kt | 262 ++++++++++++++++++ 5 files changed, 378 insertions(+), 3 deletions(-) create mode 100644 changelog/unreleased/bugfixes/6793.md diff --git a/changelog/unreleased/bugfixes/6793.md b/changelog/unreleased/bugfixes/6793.md new file mode 100644 index 00000000000..7886711c84e --- /dev/null +++ b/changelog/unreleased/bugfixes/6793.md @@ -0,0 +1 @@ +- Updated behavior of `MapboxRouteLineView::initializeLayers` to always reset the route line related layers with the options provided even if it means removing existing layers in order to apply the options. Also new instances of `MapboxRouteLineView` will result in an initialization of the layers upon the first render call. \ No newline at end of file diff --git a/libnavui-maps/src/main/java/com/mapbox/navigation/ui/maps/internal/route/line/MapboxRouteLineUtils.kt b/libnavui-maps/src/main/java/com/mapbox/navigation/ui/maps/internal/route/line/MapboxRouteLineUtils.kt index a27aff9a266..4dfbb29a1b0 100644 --- a/libnavui-maps/src/main/java/com/mapbox/navigation/ui/maps/internal/route/line/MapboxRouteLineUtils.kt +++ b/libnavui-maps/src/main/java/com/mapbox/navigation/ui/maps/internal/route/line/MapboxRouteLineUtils.kt @@ -1751,4 +1751,31 @@ internal object MapboxRouteLineUtils { .iconIgnorePlacement(true) .iconKeepUpright(true) } + + internal fun removeLayersAndSources(style: Style) { + style.removeStyleSource(RouteLayerConstants.LAYER_GROUP_1_SOURCE_ID) + style.removeStyleSource(RouteLayerConstants.LAYER_GROUP_2_SOURCE_ID) + style.removeStyleSource(RouteLayerConstants.LAYER_GROUP_3_SOURCE_ID) + style.removeStyleSource(RouteLayerConstants.WAYPOINT_SOURCE_ID) + style.removeStyleLayer(RouteLayerConstants.TOP_LEVEL_ROUTE_LINE_LAYER_ID) + style.removeStyleLayer(RouteLayerConstants.BOTTOM_LEVEL_ROUTE_LINE_LAYER_ID) + style.removeStyleLayer(RouteLayerConstants.LAYER_GROUP_1_TRAIL_CASING) + style.removeStyleLayer(RouteLayerConstants.LAYER_GROUP_1_TRAIL) + style.removeStyleLayer(RouteLayerConstants.LAYER_GROUP_1_CASING) + style.removeStyleLayer(RouteLayerConstants.LAYER_GROUP_1_MAIN) + style.removeStyleLayer(RouteLayerConstants.LAYER_GROUP_1_TRAFFIC) + style.removeStyleLayer(RouteLayerConstants.LAYER_GROUP_1_RESTRICTED) + style.removeStyleLayer(RouteLayerConstants.LAYER_GROUP_2_TRAIL_CASING) + style.removeStyleLayer(RouteLayerConstants.LAYER_GROUP_2_TRAIL) + style.removeStyleLayer(RouteLayerConstants.LAYER_GROUP_2_CASING) + style.removeStyleLayer(RouteLayerConstants.LAYER_GROUP_2_MAIN) + style.removeStyleLayer(RouteLayerConstants.LAYER_GROUP_2_TRAFFIC) + style.removeStyleLayer(RouteLayerConstants.LAYER_GROUP_2_RESTRICTED) + style.removeStyleLayer(RouteLayerConstants.LAYER_GROUP_3_TRAIL_CASING) + style.removeStyleLayer(RouteLayerConstants.LAYER_GROUP_3_TRAIL) + style.removeStyleLayer(RouteLayerConstants.LAYER_GROUP_3_CASING) + style.removeStyleLayer(RouteLayerConstants.LAYER_GROUP_3_MAIN) + style.removeStyleLayer(RouteLayerConstants.LAYER_GROUP_3_TRAFFIC) + style.removeStyleLayer(RouteLayerConstants.LAYER_GROUP_3_RESTRICTED) + } } diff --git a/libnavui-maps/src/main/java/com/mapbox/navigation/ui/maps/route/line/api/MapboxRouteLineView.kt b/libnavui-maps/src/main/java/com/mapbox/navigation/ui/maps/route/line/api/MapboxRouteLineView.kt index 3d1fcf50f1a..f53482adc50 100644 --- a/libnavui-maps/src/main/java/com/mapbox/navigation/ui/maps/route/line/api/MapboxRouteLineView.kt +++ b/libnavui-maps/src/main/java/com/mapbox/navigation/ui/maps/route/line/api/MapboxRouteLineView.kt @@ -18,6 +18,7 @@ import com.mapbox.navigation.ui.maps.internal.route.line.MapboxRouteLineUtils.ge import com.mapbox.navigation.ui.maps.internal.route.line.MapboxRouteLineUtils.layerGroup1SourceLayerIds import com.mapbox.navigation.ui.maps.internal.route.line.MapboxRouteLineUtils.layerGroup2SourceLayerIds import com.mapbox.navigation.ui.maps.internal.route.line.MapboxRouteLineUtils.layerGroup3SourceLayerIds +import com.mapbox.navigation.ui.maps.internal.route.line.MapboxRouteLineUtils.layersAreInitialized import com.mapbox.navigation.ui.maps.internal.route.line.MapboxRouteLineUtils.sourceLayerMap import com.mapbox.navigation.ui.maps.route.RouteLayerConstants import com.mapbox.navigation.ui.maps.route.RouteLayerConstants.LAYER_GROUP_1_CASING @@ -78,6 +79,8 @@ import org.jetbrains.annotations.TestOnly @UiThread class MapboxRouteLineView(options: MapboxRouteLineOptions) { + private var rebuildLayersOnFirstRender: Boolean = true + private companion object { private const val TAG = "MbxRouteLineView" } @@ -142,6 +145,8 @@ class MapboxRouteLineView(options: MapboxRouteLineOptions) { * the layers if they have not yet been initialized. If you have a use case for initializing * the layers in advance of any API calls this method may be used. * + * If the layers already exist they will be removed and re-initialized with the options provided. + * * Each [Layer] added to the map by this class is a persistent layer - it will survive style changes. * This means that if the data has not changed, it does not have to be manually redrawn after a style change. * See [Style.addPersistentStyleLayer]. @@ -149,7 +154,23 @@ class MapboxRouteLineView(options: MapboxRouteLineOptions) { * @param style a valid [Style] instance */ fun initializeLayers(style: Style) { - MapboxRouteLineUtils.initializeLayers(style, options) + resetLayers(style) + } + + /** + * Updates the [MapboxRouteLineOptions] used for the route line related layers and initializes the layers. + * If the layers already exist they will be removed and re-initialized with the options provided. + * + * Each [Layer] added to the map by this class is a persistent layer - it will survive style changes. + * This means that if the data has not changed, it does not have to be manually redrawn after a style change. + * See [Style.addPersistentStyleLayer]. + * + * @param style a valid [Style] instance + * @param options used for the route line related layers. + */ + fun initializeLayers(style: Style, options: MapboxRouteLineOptions) { + this.options = options + resetLayers(style) } /** @@ -159,7 +180,7 @@ class MapboxRouteLineView(options: MapboxRouteLineOptions) { * @param routeDrawData a [Expected] */ fun renderRouteDrawData(style: Style, routeDrawData: Expected) { - MapboxRouteLineUtils.initializeLayers(style, options) + rebuildSourcesAndLayersIfNeeded(style) jobControl.scope.launch(Dispatchers.Main) { mutex.withLock { val primaryRouteTrafficVisibility = getTrafficVisibility(style) @@ -332,7 +353,7 @@ class MapboxRouteLineView(options: MapboxRouteLineOptions) { style: Style, clearRouteLineValue: Expected ) { - MapboxRouteLineUtils.initializeLayers(style, options) + rebuildSourcesAndLayersIfNeeded(style) jobControl.scope.launch(Dispatchers.Main) { mutex.withLock { clearRouteLineValue.onValue { value -> @@ -862,4 +883,33 @@ class MapboxRouteLineView(options: MapboxRouteLineOptions) { } } } + + private fun rebuildSourcesAndLayersIfNeeded(style: Style) { + if (rebuildLayersOnFirstRender || !layersAreInitialized(style, options)) { + rebuildLayersOnFirstRender = false + resetLayers(style) + } + } + + private fun resetLayers(style: Style) { + sourceToFeatureMap.clear() + sourceToFeatureMap[MapboxRouteLineUtils.layerGroup1SourceKey] = RouteLineFeatureId(null) + sourceToFeatureMap[MapboxRouteLineUtils.layerGroup2SourceKey] = RouteLineFeatureId(null) + sourceToFeatureMap[MapboxRouteLineUtils.layerGroup3SourceKey] = RouteLineFeatureId(null) + primaryRouteLineLayerGroup = setOf() + listOf( + RouteLayerConstants.LAYER_GROUP_1_SOURCE_ID, + RouteLayerConstants.LAYER_GROUP_2_SOURCE_ID, + RouteLayerConstants.LAYER_GROUP_3_SOURCE_ID, + RouteLayerConstants.WAYPOINT_SOURCE_ID + ).forEach { + updateSource( + style, + it, + FeatureCollection.fromFeatures(listOf()) + ) + } + MapboxRouteLineUtils.removeLayersAndSources(style) + MapboxRouteLineUtils.initializeLayers(style, options) + } } diff --git a/libnavui-maps/src/test/java/com/mapbox/navigation/ui/maps/internal/route/line/MapboxRouteLineUtilsTest.kt b/libnavui-maps/src/test/java/com/mapbox/navigation/ui/maps/internal/route/line/MapboxRouteLineUtilsTest.kt index c58892e4512..91bb6db4510 100644 --- a/libnavui-maps/src/test/java/com/mapbox/navigation/ui/maps/internal/route/line/MapboxRouteLineUtilsTest.kt +++ b/libnavui-maps/src/test/java/com/mapbox/navigation/ui/maps/internal/route/line/MapboxRouteLineUtilsTest.kt @@ -2028,6 +2028,41 @@ class MapboxRouteLineUtilsTest { assertFalse(result) } + @Test + fun removeLayersAndSources() { + val style = mockk