From 32466c1f5d3048fb3bb875fa206e93fe472684c2 Mon Sep 17 00:00:00 2001 From: lodev09 Date: Tue, 5 May 2026 04:16:26 +0800 Subject: [PATCH] fix(android): clean up polyline animator on view drop Notify GoogleMapProvider from LuggPolylineView.onDropViewInstance so the PolylineAnimator (and its infinite-repeat ValueAnimator) gets cancelled even when the view is dropped without going through removeViewAt. Also guards addPolylineViewToMap against an already-registered animator entry and drops a per-frame ArrayList copy in updateAnimatedPolyline. --- .../src/main/java/com/luggmaps/LuggPolylineView.kt | 3 ++- .../java/com/luggmaps/core/GoogleMapProvider.kt | 14 ++++++++++++-- .../java/com/luggmaps/core/PolylineAnimator.kt | 2 +- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/android/src/main/java/com/luggmaps/LuggPolylineView.kt b/android/src/main/java/com/luggmaps/LuggPolylineView.kt index 77f63ff..6125ebf 100644 --- a/android/src/main/java/com/luggmaps/LuggPolylineView.kt +++ b/android/src/main/java/com/luggmaps/LuggPolylineView.kt @@ -8,6 +8,7 @@ import com.google.android.gms.maps.model.Polyline interface LuggPolylineViewDelegate { fun polylineViewDidUpdate(polylineView: LuggPolylineView) + fun polylineViewDidDrop(polylineView: LuggPolylineView) } data class AnimatedOptions(val duration: Long = 2150L, val easing: String = "linear", val trailLength: Float = 1f, val delay: Long = 0L) @@ -67,8 +68,8 @@ class LuggPolylineView(context: Context) : ReactViewGroup(context) { } fun onDropViewInstance() { + delegate?.polylineViewDidDrop(this) delegate = null - polyline?.remove() polyline = null } } diff --git a/android/src/main/java/com/luggmaps/core/GoogleMapProvider.kt b/android/src/main/java/com/luggmaps/core/GoogleMapProvider.kt index 58f6626..0283d3e 100644 --- a/android/src/main/java/com/luggmaps/core/GoogleMapProvider.kt +++ b/android/src/main/java/com/luggmaps/core/GoogleMapProvider.kt @@ -598,6 +598,10 @@ class GoogleMapProvider(private val context: Context) : syncPolylineView(polylineView) } + override fun polylineViewDidDrop(polylineView: LuggPolylineView) { + teardownPolyline(polylineView) + } + // endregion // region PolygonViewDelegate @@ -773,8 +777,12 @@ class GoogleMapProvider(private val context: Context) : } override fun removePolylineView(polylineView: LuggPolylineView) { - polylineAnimators[polylineView]?.destroy() - polylineAnimators.remove(polylineView) + teardownPolyline(polylineView) + } + + private fun teardownPolyline(polylineView: LuggPolylineView) { + pendingPolylineViews.remove(polylineView) + polylineAnimators.remove(polylineView)?.destroy() polylineView.polyline?.remove() polylineView.polyline = null } @@ -812,6 +820,8 @@ class GoogleMapProvider(private val context: Context) : private fun addPolylineViewToMap(polylineView: LuggPolylineView) { val map = googleMap ?: return + polylineAnimators.remove(polylineView)?.destroy() + val options = PolylineOptions() .width(polylineView.strokeWidth.dpToPx()) .zIndex(polylineView.zIndex) diff --git a/android/src/main/java/com/luggmaps/core/PolylineAnimator.kt b/android/src/main/java/com/luggmaps/core/PolylineAnimator.kt index 5a9dbcb..1b697bc 100644 --- a/android/src/main/java/com/luggmaps/core/PolylineAnimator.kt +++ b/android/src/main/java/com/luggmaps/core/PolylineAnimator.kt @@ -249,7 +249,7 @@ class PolylineAnimator { // Clear spans before setting points to prevent IndexOutOfBoundsException // when the new points list is shorter than what existing spans reference poly.color = strokeColors.firstOrNull() ?: Color.BLACK - poly.points = ArrayList(reusablePoints) + poly.points = reusablePoints if (strokeColors.size > 1) { val segmentCount = reusablePoints.size - 1