Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public class NavModule extends NativeNavModuleSpec
private NavViewManager mNavViewManager;
private final CopyOnWriteArrayList<NavigationReadyListener> mNavigationReadyListeners =
new CopyOnWriteArrayList<>();
private boolean mIsListeningRoadSnappedLocation = false;
private volatile boolean mIsListeningRoadSnappedLocation = false;
private LocationListener mLocationListener;
private Navigator.ArrivalListener mArrivalListener;
private Navigator.RouteChangedListener mRouteChangedListener;
Expand Down Expand Up @@ -167,8 +167,6 @@ public void cleanup(final Promise promise) {
}

mIsListeningRoadSnappedLocation = false;
removeLocationListener();
removeNavigationListeners();
mWaypoints.clear();

for (NavigationReadyListener listener : mNavigationReadyListeners) {
Expand All @@ -178,6 +176,11 @@ public void cleanup(final Promise promise) {
final Navigator navigator = mNavigator;
UiThreadUtil.runOnUiThread(
() -> {
// Remove listeners on UI thread to serialize with callback dispatch.
// This reduces the chance of triggering a race condition in the Navigation SDK
// where callbacks may still be in-flight during removal.
removeLocationListener();
removeNavigationListeners();
navigator.clearDestinations();
navigator.stopGuidance();
navigator.getSimulator().unsetUserLocation();
Expand Down Expand Up @@ -933,20 +936,31 @@ public void resetTermsAccepted(final Promise promise) {

@Override
public void startUpdatingLocation(final Promise promise) {
registerLocationListener();
mIsListeningRoadSnappedLocation = true;
promise.resolve(null);
// Register listener on UI thread to serialize with callback dispatch and allow
// safe remove-and-recreate.
UiThreadUtil.runOnUiThread(
() -> {
registerLocationListener();
promise.resolve(null);
});
}

@Override
public void stopUpdatingLocation(final Promise promise) {
mIsListeningRoadSnappedLocation = false;
removeLocationListener();
promise.resolve(null);
// Remove the listener on UI thread to serialize with callback dispatch.
// This avoids the race condition in the Navigation SDK.
UiThreadUtil.runOnUiThread(
() -> {
removeLocationListener();
promise.resolve(null);
});
}

private void registerLocationListener() {
// Unregister existing location listener if available.
// Remove existing listener first, then recreate. This is safe when called
// from UI thread as it serializes with callback dispatch.
removeLocationListener();

if (mRoadSnappedLocationProvider != null) {
Expand Down
Loading