Skip to content

Commit 7019a86

Browse files
committed
fix: threading issues
1 parent 092993f commit 7019a86

13 files changed

+391
-510
lines changed

android/src/main/java/com/rngooglemapsplus/GoogleMapsViewImpl.kt

Lines changed: 337 additions & 484 deletions
Large diffs are not rendered by default.

android/src/main/java/com/rngooglemapsplus/MapCircleBuilder.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import android.graphics.Color
44
import com.facebook.react.uimanager.PixelUtil.dpToPx
55
import com.google.android.gms.maps.model.Circle
66
import com.google.android.gms.maps.model.CircleOptions
7+
import com.rngooglemapsplus.extensions.onUi
78
import com.rngooglemapsplus.extensions.toColor
89
import com.rngooglemapsplus.extensions.toLatLng
910

@@ -23,7 +24,7 @@ class MapCircleBuilder {
2324
prev: RNCircle,
2425
next: RNCircle,
2526
circle: Circle,
26-
) {
27+
) = onUi {
2728
if (prev.center.latitude != next.center.latitude ||
2829
prev.center.longitude != next.center.longitude
2930
) {
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.rngooglemapsplus.extensions
2+
3+
import com.facebook.react.bridge.UiThreadUtil
4+
import kotlinx.coroutines.CompletableDeferred
5+
import kotlinx.coroutines.runBlocking
6+
7+
inline fun onUi(crossinline block: () -> Unit) {
8+
if (UiThreadUtil.isOnUiThread()) {
9+
block()
10+
} else {
11+
UiThreadUtil.runOnUiThread { block() }
12+
}
13+
}
14+
15+
inline fun <T> onUiSync(crossinline block: () -> T): T {
16+
if (UiThreadUtil.isOnUiThread()) return block()
17+
val result = CompletableDeferred<T>()
18+
UiThreadUtil.runOnUiThread {
19+
runCatching(block).onSuccess(result::complete).onFailure(result::completeExceptionally)
20+
}
21+
return runBlocking { result.await() }
22+
}

android/src/main/java/com/rngooglemapsplus/MapMarkerBuilder.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import com.google.android.gms.maps.model.BitmapDescriptorFactory
1616
import com.google.android.gms.maps.model.Marker
1717
import com.google.android.gms.maps.model.MarkerOptions
1818
import com.rngooglemapsplus.extensions.markerStyleEquals
19+
import com.rngooglemapsplus.extensions.onUi
1920
import com.rngooglemapsplus.extensions.styleHash
2021
import com.rngooglemapsplus.extensions.toLatLng
2122
import kotlinx.coroutines.CoroutineScope
@@ -28,6 +29,7 @@ import kotlinx.coroutines.withContext
2829
import java.net.HttpURLConnection
2930
import java.net.URL
3031
import java.net.URLDecoder
32+
import java.util.concurrent.ConcurrentHashMap
3133
import kotlin.coroutines.coroutineContext
3234

3335
class MapMarkerBuilder(
@@ -42,7 +44,7 @@ class MapMarkerBuilder(
4244
): Int = 1
4345
}
4446

45-
private val jobsById = mutableMapOf<String, Job>()
47+
private val jobsById = ConcurrentHashMap<String, Job>()
4648

4749
init {
4850
// / TODO: refactor with androidsvg 1.5 release
@@ -162,7 +164,7 @@ class MapMarkerBuilder(
162164
prev: RNMarker,
163165
next: RNMarker,
164166
marker: Marker,
165-
) {
167+
) = onUi {
166168
if (prev.coordinate.latitude != next.coordinate.latitude ||
167169
prev.coordinate.longitude != next.coordinate.longitude
168170
) {

android/src/main/java/com/rngooglemapsplus/MapPolygonBuilder.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import android.graphics.Color
44
import com.facebook.react.uimanager.PixelUtil.dpToPx
55
import com.google.android.gms.maps.model.Polygon
66
import com.google.android.gms.maps.model.PolygonOptions
7+
import com.rngooglemapsplus.extensions.onUi
78
import com.rngooglemapsplus.extensions.toColor
89
import com.rngooglemapsplus.extensions.toLatLng
910

@@ -30,7 +31,7 @@ class MapPolygonBuilder {
3031
prev: RNPolygon,
3132
next: RNPolygon,
3233
poly: Polygon,
33-
) {
34+
) = onUi {
3435
val coordsChanged =
3536
prev.coordinates.size != next.coordinates.size ||
3637
!prev.coordinates.zip(next.coordinates).all { (a, b) ->

android/src/main/java/com/rngooglemapsplus/MapPolylineBuilder.kt.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import com.google.android.gms.maps.model.Polyline
99
import com.google.android.gms.maps.model.PolylineOptions
1010
import com.google.android.gms.maps.model.RoundCap
1111
import com.google.android.gms.maps.model.SquareCap
12+
import com.rngooglemapsplus.extensions.onUi
1213
import com.rngooglemapsplus.extensions.toColor
1314
import com.rngooglemapsplus.extensions.toLatLng
1415

@@ -34,7 +35,7 @@ class MapPolylineBuilder {
3435
prev: RNPolyline,
3536
next: RNPolyline,
3637
polyline: Polyline,
37-
) {
38+
) = onUi {
3839
val coordsChanged =
3940
prev.coordinates.size != next.coordinates.size ||
4041
!prev.coordinates.zip(next.coordinates).all { (a, b) ->

android/src/main/java/com/rngooglemapsplus/RNGoogleMapsPlusView.kt

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package com.rngooglemapsplus
22

33
import com.facebook.proguard.annotations.DoNotStrip
4-
import com.facebook.react.bridge.UiThreadUtil
54
import com.facebook.react.uimanager.ThemedReactContext
65
import com.google.android.gms.maps.GoogleMapOptions
76
import com.google.android.gms.maps.model.MapStyleOptions
@@ -155,7 +154,7 @@ class RNGoogleMapsPlusView(
155154

156155
!prev.markerEquals(next) ->
157156
view.updateMarker(id) { marker ->
158-
onUi { markerBuilder.update(prev, next, marker) }
157+
markerBuilder.update(prev, next, marker)
159158
}
160159
}
161160
}
@@ -179,7 +178,7 @@ class RNGoogleMapsPlusView(
179178

180179
!prev.polylineEquals(next) ->
181180
view.updatePolyline(id) { polyline ->
182-
onUi { polylineBuilder.update(prev, next, polyline) }
181+
polylineBuilder.update(prev, next, polyline)
183182
}
184183
}
185184
}
@@ -204,7 +203,7 @@ class RNGoogleMapsPlusView(
204203

205204
!prev.polygonEquals(next) ->
206205
view.updatePolygon(id) { polygon ->
207-
onUi { polygonBuilder.update(prev, next, polygon) }
206+
polygonBuilder.update(prev, next, polygon)
208207
}
209208
}
210209
}
@@ -229,7 +228,7 @@ class RNGoogleMapsPlusView(
229228

230229
!prev.circleEquals(next) ->
231230
view.updateCircle(id) { circle ->
232-
onUi { circleBuilder.update(prev, next, circle) }
231+
circleBuilder.update(prev, next, circle)
233232
}
234233
}
235234
}
@@ -416,14 +415,12 @@ class RNGoogleMapsPlusView(
416415
animated: Boolean?,
417416
durationMs: Double?,
418417
) {
419-
onUi {
420-
val current = view.currentCamera
421-
view.setCamera(
422-
camera.toCameraPosition(current),
423-
animated == true,
424-
durationMs?.toInt() ?: 3000,
425-
)
426-
}
418+
val current = view.currentCamera
419+
view.setCamera(
420+
camera.toCameraPosition(current),
421+
animated == true,
422+
durationMs?.toInt() ?: 3000,
423+
)
427424
}
428425

429426
override fun setCameraToCoordinates(
@@ -481,11 +478,3 @@ class RNGoogleMapsPlusView(
481478

482479
override fun isGooglePlayServicesAvailable(): Boolean = playServiceHandler.isPlayServicesAvailable()
483480
}
484-
485-
private inline fun onUi(crossinline block: () -> Unit) {
486-
if (UiThreadUtil.isOnUiThread()) {
487-
block()
488-
} else {
489-
UiThreadUtil.runOnUiThread { block() }
490-
}
491-
}

ios/MapCircleBuilder.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import GoogleMaps
22

33
final class MapCircleBuilder {
4+
@MainActor
45
func build(_ c: RNCircle) -> GMSCircle {
56
let circle = GMSCircle()
67
circle.position = c.center.toCLLocationCoordinate2D()
@@ -14,6 +15,7 @@ final class MapCircleBuilder {
1415
return circle
1516
}
1617

18+
@MainActor
1719
func update(_ prev: RNCircle, _ next: RNCircle, _ c: GMSCircle) {
1820
if prev.center.latitude != next.center.latitude
1921
|| prev.center.longitude != next.center.longitude {

ios/MapHeatmapBuilder.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import GoogleMapsUtils
44
import UIKit
55

66
final class MapHeatmapBuilder {
7+
@MainActor
78
func build(_ h: RNHeatmap) -> GMUHeatmapTileLayer {
89
let heatmap = GMUHeatmapTileLayer()
910
heatmap.weightedData = h.weightedData.toWeightedLatLngs()

ios/MapMarkerBuilder.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ final class MapMarkerBuilder {
1010
}()
1111
private var tasks: [String: Task<Void, Never>] = [:]
1212

13+
@MainActor
1314
func build(_ m: RNMarker, icon: UIImage?) -> GMSMarker {
1415
let marker = GMSMarker(
1516
position: m.coordinate.toCLLocationCoordinate2D()
@@ -160,11 +161,13 @@ final class MapMarkerBuilder {
160161
tasks[id] = task
161162
}
162163

164+
@MainActor
163165
func cancelIconTask(_ id: String) {
164166
tasks[id]?.cancel()
165167
tasks.removeValue(forKey: id)
166168
}
167169

170+
@MainActor
168171
func cancelAllIconTasks() {
169172
let ids = Array(tasks.keys)
170173
for id in ids {
@@ -174,6 +177,7 @@ final class MapMarkerBuilder {
174177
iconCache.removeAllObjects()
175178
}
176179

180+
@MainActor
177181
private func renderUIImage(_ m: RNMarker, _ scale: CGFloat) async -> UIImage? {
178182
guard let iconSvg = m.iconSvg,
179183
let data = iconSvg.svgString.data(using: .utf8)

0 commit comments

Comments
 (0)