From 2540c5a09f22f554fef893811de56f80ab6abb1c Mon Sep 17 00:00:00 2001 From: danesfeder Date: Thu, 6 Dec 2018 13:05:09 -0500 Subject: [PATCH] Remove GeoJson sources onDestroy --- .../ComponentNavigationActivity.java | 2 +- .../NavigationMapRouteActivity.java | 3 +- .../testapp/example/ui/ExampleActivity.kt | 2 +- .../ui/v5/map/NavigationMapboxMap.java | 16 +++---- .../ui/v5/route/FeatureProcessingTask.java | 11 +++-- .../navigation/ui/v5/route/MapRouteArrow.java | 19 +++++---- .../navigation/ui/v5/route/MapRouteLine.java | 40 ++++++++++-------- .../ui/v5/route/NavigationMapRoute.java | 32 +++++++++++--- .../ui/v5/route/PrimaryRouteUpdateTask.java | 13 ++++-- .../ui/v5/route/NavigationMapRouteTest.java | 42 +++++++++++++++++++ 10 files changed, 127 insertions(+), 53 deletions(-) diff --git a/app/src/main/java/com/mapbox/services/android/navigation/testapp/activity/navigationui/ComponentNavigationActivity.java b/app/src/main/java/com/mapbox/services/android/navigation/testapp/activity/navigationui/ComponentNavigationActivity.java index 7ea36605a8d..20eefebb1aa 100644 --- a/app/src/main/java/com/mapbox/services/android/navigation/testapp/activity/navigationui/ComponentNavigationActivity.java +++ b/app/src/main/java/com/mapbox/services/android/navigation/testapp/activity/navigationui/ComponentNavigationActivity.java @@ -416,7 +416,7 @@ private void adjustMapPaddingForNavigation() { } private void resetMapAfterNavigation() { - navigationMap.updateRouteVisibility(false); + navigationMap.removeRoute(); navigationMap.clearMarkers(); navigation.stopNavigation(); moveCameraOverhead(); diff --git a/app/src/main/java/com/mapbox/services/android/navigation/testapp/activity/navigationui/NavigationMapRouteActivity.java b/app/src/main/java/com/mapbox/services/android/navigation/testapp/activity/navigationui/NavigationMapRouteActivity.java index 877c94b094b..c2a8838ab65 100644 --- a/app/src/main/java/com/mapbox/services/android/navigation/testapp/activity/navigationui/NavigationMapRouteActivity.java +++ b/app/src/main/java/com/mapbox/services/android/navigation/testapp/activity/navigationui/NavigationMapRouteActivity.java @@ -110,8 +110,7 @@ public void onMapLongClick(@NonNull LatLng point) { } else { originMarker = null; destinationMarker = null; - navigationMapRoute.updateRouteVisibilityTo(false); - navigationMapRoute.updateRouteArrowVisibilityTo(false); + navigationMapRoute.removeRoute(); } } diff --git a/app/src/main/java/com/mapbox/services/android/navigation/testapp/example/ui/ExampleActivity.kt b/app/src/main/java/com/mapbox/services/android/navigation/testapp/example/ui/ExampleActivity.kt index 0c4b832c77e..6191c157ce2 100644 --- a/app/src/main/java/com/mapbox/services/android/navigation/testapp/example/ui/ExampleActivity.kt +++ b/app/src/main/java/com/mapbox/services/android/navigation/testapp/example/ui/ExampleActivity.kt @@ -221,7 +221,7 @@ class ExampleActivity : HistoryActivity(), ExampleView { } override fun removeRoute() { - map?.updateRouteVisibility(false) + map?.removeRoute() } override fun clearMarkers() { diff --git a/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/map/NavigationMapboxMap.java b/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/map/NavigationMapboxMap.java index 67a9cad8abc..7a1d804212c 100644 --- a/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/map/NavigationMapboxMap.java +++ b/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/map/NavigationMapboxMap.java @@ -7,6 +7,7 @@ import android.os.Bundle; import android.os.PersistableBundle; import android.support.annotation.NonNull; +import android.support.v4.app.Fragment; import android.support.v4.app.FragmentActivity; import com.mapbox.api.directions.v5.models.DirectionsRoute; @@ -283,16 +284,11 @@ public void showAlternativeRoutes(boolean alternativesVisible) { } /** - * This method will update the route visibility. - *

- * The visibility will include the main route, alternatives, - * and the upcoming maneuver arrow. - * - * @param isVisible true to show, false otherwise. + * Will remove the drawn route displayed on the map. Does nothing + * if no route is drawn. */ - public void updateRouteVisibility(boolean isVisible) { - mapRoute.updateRouteVisibilityTo(isVisible); - mapRoute.updateRouteArrowVisibilityTo(isVisible); + public void removeRoute() { + mapRoute.removeRoute(); } /** @@ -427,7 +423,7 @@ public void onStop() { } /** - * Should be used in {@link FragmentActivity#onDestroy()} to ensure proper + * Should be used in {@link FragmentActivity#onDestroy()} or {@link Fragment#onDestroyView()} to ensure proper * accounting for the lifecycle. */ public void onDestroy() { diff --git a/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/route/FeatureProcessingTask.java b/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/route/FeatureProcessingTask.java index d9210894546..25473386630 100644 --- a/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/route/FeatureProcessingTask.java +++ b/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/route/FeatureProcessingTask.java @@ -10,6 +10,7 @@ import com.mapbox.geojson.LineString; import com.mapbox.geojson.Point; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -19,13 +20,13 @@ class FeatureProcessingTask extends AsyncTask { private final List routes; - private final OnRouteFeaturesProcessedCallback callback; private final List routeFeatureCollections = new ArrayList<>(); + private final WeakReference callbackWeakReference; private final HashMap routeLineStrings = new HashMap<>(); FeatureProcessingTask(List routes, OnRouteFeaturesProcessedCallback callback) { this.routes = routes; - this.callback = callback; + this.callbackWeakReference = new WeakReference<>(callback); } @Override @@ -42,7 +43,11 @@ protected Void doInBackground(Void... voids) { @Override protected void onPostExecute(Void result) { super.onPostExecute(result); - callback.onRouteFeaturesProcessed(routeFeatureCollections, routeLineStrings); + Runtime.getRuntime().gc(); + OnRouteFeaturesProcessedCallback callback = callbackWeakReference.get(); + if (callback != null) { + callback.onRouteFeaturesProcessed(routeFeatureCollections, routeLineStrings); + } } private FeatureCollection createRouteFeatureCollection(DirectionsRoute route, boolean isPrimary) { diff --git a/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/route/MapRouteArrow.java b/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/route/MapRouteArrow.java index 47621e2905b..504230e6bd6 100644 --- a/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/route/MapRouteArrow.java +++ b/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/route/MapRouteArrow.java @@ -11,6 +11,7 @@ import android.support.v7.content.res.AppCompatResources; import com.mapbox.geojson.Feature; +import com.mapbox.geojson.FeatureCollection; import com.mapbox.geojson.LineString; import com.mapbox.geojson.Point; import com.mapbox.mapboxsdk.maps.MapView; @@ -86,8 +87,6 @@ class MapRouteArrow { private List arrowLayers; private GeoJsonSource arrowShaftGeoJsonSource; private GeoJsonSource arrowHeadGeoJsonSource; - private Feature arrowShaftGeoJsonFeature = Feature.fromGeometry(Point.fromLngLat(0, 0)); - private Feature arrowHeadGeoJsonFeature = Feature.fromGeometry(Point.fromLngLat(0, 0)); private final MapView mapView; private final MapboxMap mapboxMap; @@ -135,6 +134,8 @@ void onDestroy() { for (Layer arrowLayer : arrowLayers) { mapboxMap.removeLayer(arrowLayer); } + mapboxMap.removeSource(arrowHeadGeoJsonSource); + mapboxMap.removeSource(arrowShaftGeoJsonSource); } private List obtainArrowPointsFrom(RouteProgress routeProgress) { @@ -157,13 +158,13 @@ private List obtainArrowPointsFrom(RouteProgress routeProgress) { private void updateArrowShaftWith(List points) { LineString shaft = LineString.fromLngLats(points); - arrowShaftGeoJsonFeature = Feature.fromGeometry(shaft); + Feature arrowShaftGeoJsonFeature = Feature.fromGeometry(shaft); arrowShaftGeoJsonSource.setGeoJson(arrowShaftGeoJsonFeature); } private void updateArrowHeadWith(List points) { double azimuth = TurfMeasurement.bearing(points.get(points.size() - 2), points.get(points.size() - 1)); - arrowHeadGeoJsonFeature = Feature.fromGeometry(points.get(points.size() - 1)); + Feature arrowHeadGeoJsonFeature = Feature.fromGeometry(points.get(points.size() - 1)); arrowHeadGeoJsonFeature.addNumberProperty(ARROW_BEARING, (float) MathUtils.wrap(azimuth, 0, MAX_DEGREES)); arrowHeadGeoJsonSource.setGeoJson(arrowHeadGeoJsonFeature); } @@ -186,13 +187,13 @@ private void initialize() { mapboxMap.addLayerAbove(shaftLayer, headCasingLayer.getId()); mapboxMap.addLayerAbove(headLayer, shaftLayer.getId()); - initializeArrowLayers(shaftLayer, shaftCasingLayer, headLayer, headCasingLayer); + createArrowLayerList(shaftLayer, shaftCasingLayer, headLayer, headCasingLayer); } private void initializeArrowShaft() { arrowShaftGeoJsonSource = new GeoJsonSource( ARROW_SHAFT_SOURCE_ID, - arrowShaftGeoJsonFeature, + FeatureCollection.fromFeatures(new Feature[] {}), new GeoJsonOptions().withMaxZoom(16) ); mapboxMap.addSource(arrowShaftGeoJsonSource); @@ -201,7 +202,7 @@ private void initializeArrowShaft() { private void initializeArrowHead() { arrowHeadGeoJsonSource = new GeoJsonSource( ARROW_HEAD_SOURCE_ID, - arrowShaftGeoJsonFeature, + FeatureCollection.fromFeatures(new Feature[] {}), new GeoJsonOptions().withMaxZoom(16) ); mapboxMap.addSource(arrowHeadGeoJsonSource); @@ -340,8 +341,8 @@ private SymbolLayer createArrowHeadCasingLayer() { ); } - private void initializeArrowLayers(LineLayer shaftLayer, LineLayer shaftCasingLayer, SymbolLayer headLayer, - SymbolLayer headCasingLayer) { + private void createArrowLayerList(LineLayer shaftLayer, LineLayer shaftCasingLayer, SymbolLayer headLayer, + SymbolLayer headCasingLayer) { arrowLayers = new ArrayList<>(); arrowLayers.add(shaftCasingLayer); arrowLayers.add(shaftLayer); diff --git a/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/route/MapRouteLine.java b/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/route/MapRouteLine.java index 9ea74cdc339..5ec30ef3c82 100644 --- a/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/route/MapRouteLine.java +++ b/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/route/MapRouteLine.java @@ -206,7 +206,7 @@ void updateVisibilityTo(boolean isVisible) { updateAllLayersVisibilityTo(isVisible); } - boolean retrieveVisibilty() { + boolean retrieveVisibility() { return isVisible; } @@ -236,6 +236,8 @@ void onDestroy() { for (Layer routeLayer : routeLayers) { mapboxMap.removeLayer(routeLayer); } + mapboxMap.removeSource(routeLineSource); + mapboxMap.removeSource(wayPointSource); } private void drawRoutes(List routeFeatureCollections) { @@ -266,18 +268,20 @@ private void clearRouteListData() { } private void generateRouteFeatureCollectionsFrom(List routes) { - new FeatureProcessingTask(routes, new OnRouteFeaturesProcessedCallback() { - @Override - public void onRouteFeaturesProcessed(List routeFeatureCollections, - HashMap routeLineStrings) { - MapRouteLine.this.routeFeatureCollections.addAll(routeFeatureCollections); - MapRouteLine.this.routeLineStrings.putAll(routeLineStrings); - drawRoutes(routeFeatureCollections); - drawWayPoints(); - } - }).execute(); + new FeatureProcessingTask(routes, routeFeaturesProcessedCallback).execute(); } + private OnRouteFeaturesProcessedCallback routeFeaturesProcessedCallback = new OnRouteFeaturesProcessedCallback() { + @Override + public void onRouteFeaturesProcessed(List routeFeatureCollections, + HashMap routeLineStrings) { + MapRouteLine.this.routeFeatureCollections.addAll(routeFeatureCollections); + MapRouteLine.this.routeLineStrings.putAll(routeLineStrings); + drawRoutes(routeFeatureCollections); + drawWayPoints(); + } + }; + private void drawWayPoints() { DirectionsRoute primaryRoute = directionsRoutes.get(primaryRouteIndex); wayPointFeatureCollection = buildWayPointFeatureCollectionFrom(primaryRoute); @@ -306,14 +310,16 @@ private void updateRoutesFor(int newPrimaryIndex) { if (newPrimaryIndex < 0 || newPrimaryIndex > routeFeatureCollections.size() - 1) { return; } - new PrimaryRouteUpdateTask(newPrimaryIndex, routeFeatureCollections, new OnPrimaryRouteUpdatedCallback() { - @Override - public void onPrimaryRouteUpdated(List updatedRouteCollections) { - drawRoutes(updatedRouteCollections); - } - }).execute(); + new PrimaryRouteUpdateTask(newPrimaryIndex, routeFeatureCollections, primaryRouteUpdatedCallback).execute(); } + private OnPrimaryRouteUpdatedCallback primaryRouteUpdatedCallback = new OnPrimaryRouteUpdatedCallback() { + @Override + public void onPrimaryRouteUpdated(List updatedRouteCollections) { + drawRoutes(updatedRouteCollections); + } + }; + private void findRouteBelowLayerId() { if (belowLayer == null || belowLayer.isEmpty()) { List styleLayers = mapboxMap.getLayers(); diff --git a/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/route/NavigationMapRoute.java b/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/route/NavigationMapRoute.java index e853546f207..b6ca3a7bca5 100644 --- a/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/route/NavigationMapRoute.java +++ b/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/route/NavigationMapRoute.java @@ -42,8 +42,8 @@ public class NavigationMapRoute implements LifecycleObserver { private final String belowLayer; private final MapboxMap mapboxMap; private final MapView mapView; - private final MapRouteClickListener mapRouteClickListener; - private final MapRouteProgressChangeListener mapRouteProgressChangeListener; + private MapRouteClickListener mapRouteClickListener; + private MapRouteProgressChangeListener mapRouteProgressChangeListener; private boolean isMapClickListenerAdded = false; private MapView.OnDidFinishLoadingStyleListener didFinishLoadingStyleListener; private boolean isDidFinishLoadingStyleListenerAdded = false; @@ -207,6 +207,18 @@ public void addRoutes(@NonNull @Size(min = 1) List directionsRo routeLine.draw(directionsRoutes); } + /** + * Hides all routes / route arrows on the map drawn by this class. + * + * @deprecated you can now use a combination of {@link NavigationMapRoute#updateRouteVisibilityTo(boolean)} + * and {@link NavigationMapRoute#updateRouteArrowVisibilityTo(boolean)} to hide the route line and arrow. + */ + @Deprecated + public void removeRoute() { + updateRouteVisibilityTo(false); + updateRouteArrowVisibilityTo(false); + } + /** * Hides all routes on the map drawn by this class. * @@ -301,8 +313,8 @@ public void onStop() { } /** - * This method should be added in your {@link Activity#onDestroy()} or {@link Fragment#onDestroyView()} - * to handle removing resources that were added to the map. + * This method should be added in your {@link Activity#onDestroy()} or + * {@link android.support.v4.app.Fragment#onDestroyView()} to handle removing resources that were added to the map. */ @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) public void onDestroy() { @@ -352,8 +364,16 @@ private void redraw() { List routes = routeLine.retrieveDirectionsRoutes(); boolean alternativesVisible = routeLine.retrieveAlternativesVisible(); int primaryRouteIndex = routeLine.retrievePrimaryRouteIndex(); - boolean isVisible = routeLine.retrieveVisibilty(); - routeLine = new MapRouteLine(mapView.getContext(), mapboxMap, styleRes, belowLayer); + boolean isVisible = routeLine.retrieveVisibility(); + buildNewRouteLine(); routeLine.redraw(routes, alternativesVisible, primaryRouteIndex, isVisible); } + + private void buildNewRouteLine() { + routeLine = new MapRouteLine(mapView.getContext(), mapboxMap, styleRes, belowLayer); + mapboxMap.removeOnMapClickListener(mapRouteClickListener); + mapRouteClickListener = new MapRouteClickListener(routeLine); + mapboxMap.addOnMapClickListener(mapRouteClickListener); + mapRouteProgressChangeListener = new MapRouteProgressChangeListener(routeLine, routeArrow); + } } \ No newline at end of file diff --git a/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/route/PrimaryRouteUpdateTask.java b/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/route/PrimaryRouteUpdateTask.java index bd1f4b79b9a..8a9fb10042d 100644 --- a/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/route/PrimaryRouteUpdateTask.java +++ b/libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/route/PrimaryRouteUpdateTask.java @@ -5,6 +5,7 @@ import com.mapbox.geojson.Feature; import com.mapbox.geojson.FeatureCollection; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; @@ -15,13 +16,13 @@ class PrimaryRouteUpdateTask extends AsyncTask routeFeatureCollections; - private final OnPrimaryRouteUpdatedCallback callback; + private final WeakReference callbackWeakReference; PrimaryRouteUpdateTask(int newPrimaryIndex, List routeFeatureCollections, - OnPrimaryRouteUpdatedCallback callback) { + OnPrimaryRouteUpdatedCallback callback) { this.newPrimaryIndex = newPrimaryIndex; this.routeFeatureCollections = routeFeatureCollections; - this.callback = callback; + this.callbackWeakReference = new WeakReference<>(callback); } @Override @@ -52,6 +53,10 @@ protected List doInBackground(Void... voids) { @Override protected void onPostExecute(List updatedRouteCollections) { - callback.onPrimaryRouteUpdated(updatedRouteCollections); + Runtime.getRuntime().gc(); + OnPrimaryRouteUpdatedCallback callback = callbackWeakReference.get(); + if (callback != null) { + callback.onPrimaryRouteUpdated(updatedRouteCollections); + } } } diff --git a/libandroid-navigation-ui/src/test/java/com/mapbox/services/android/navigation/ui/v5/route/NavigationMapRouteTest.java b/libandroid-navigation-ui/src/test/java/com/mapbox/services/android/navigation/ui/v5/route/NavigationMapRouteTest.java index 897fda4e028..ec259e1ee15 100644 --- a/libandroid-navigation-ui/src/test/java/com/mapbox/services/android/navigation/ui/v5/route/NavigationMapRouteTest.java +++ b/libandroid-navigation-ui/src/test/java/com/mapbox/services/android/navigation/ui/v5/route/NavigationMapRouteTest.java @@ -257,6 +257,48 @@ public void updateRouteVisibilityTo_routeLineVisibilityIsUpdated() { verify(mockedMapRouteLine).updateVisibilityTo(isVisible); } + @Test + public void removeRoute_routeLineVisibilityIsUpdated() { + MapboxNavigation mockedNavigation = mock(MapboxNavigation.class); + MapView mockedMapView = mock(MapView.class); + MapboxMap mockedMapboxMap = mock(MapboxMap.class); + int mockedStyleRes = 0; + MapRouteClickListener mockedMapClickListener = mock(MapRouteClickListener.class); + MapView.OnDidFinishLoadingStyleListener mockedDidFinishLoadingStyleListener = + mock(MapView.OnDidFinishLoadingStyleListener.class); + MapRouteProgressChangeListener mockedProgressChangeListener = mock(MapRouteProgressChangeListener.class); + MapRouteLine mockedMapRouteLine = mock(MapRouteLine.class); + MapRouteArrow mockedMapRouteArrow = mock(MapRouteArrow.class); + NavigationMapRoute theNavigationMapRoute = new NavigationMapRoute(mockedNavigation, mockedMapView, mockedMapboxMap, + mockedStyleRes, "", mockedMapClickListener, mockedDidFinishLoadingStyleListener, + mockedProgressChangeListener, mockedMapRouteLine, mockedMapRouteArrow); + + theNavigationMapRoute.removeRoute(); + + verify(mockedMapRouteLine).updateVisibilityTo(false); + } + + @Test + public void removeRoute_routeArrowVisibilityIsUpdated() { + MapboxNavigation mockedNavigation = mock(MapboxNavigation.class); + MapView mockedMapView = mock(MapView.class); + MapboxMap mockedMapboxMap = mock(MapboxMap.class); + int mockedStyleRes = 0; + MapRouteClickListener mockedMapClickListener = mock(MapRouteClickListener.class); + MapView.OnDidFinishLoadingStyleListener mockedDidFinishLoadingStyleListener = + mock(MapView.OnDidFinishLoadingStyleListener.class); + MapRouteProgressChangeListener mockedProgressChangeListener = mock(MapRouteProgressChangeListener.class); + MapRouteLine mockedMapRouteLine = mock(MapRouteLine.class); + MapRouteArrow mockedMapRouteArrow = mock(MapRouteArrow.class); + NavigationMapRoute theNavigationMapRoute = new NavigationMapRoute(mockedNavigation, mockedMapView, mockedMapboxMap, + mockedStyleRes, "", mockedMapClickListener, mockedDidFinishLoadingStyleListener, + mockedProgressChangeListener, mockedMapRouteLine, mockedMapRouteArrow); + + theNavigationMapRoute.removeRoute(); + + verify(mockedMapRouteArrow).updateVisibilityTo(false); + } + @Test public void updateRouteVisibilityTo_progressChangeVisibilityIsUpdated() { MapboxNavigation mockedNavigation = mock(MapboxNavigation.class);