Skip to content

Commit e97e48a

Browse files
committed
fix: fragment disposal issues
- add better null checks for Android and iOS views
1 parent a808726 commit e97e48a

File tree

11 files changed

+417
-197
lines changed

11 files changed

+417
-197
lines changed

android/src/main/java/com/google/android/react/navsdk/Command.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ public enum Command {
2323
SET_NAVIGATION_UI_ENABLED(5, "setNavigationUIEnabled"),
2424
SET_FOLLOWING_PERSPECTIVE(6, "setFollowingPerspective"),
2525
SET_NIGHT_MODE(7, "setNightMode"),
26-
DELETE_FRAGMENT(8, "deleteFragment"),
2726
SET_SPEEDOMETER_ENABLED(9, "setSpeedometerEnabled"),
2827
SET_SPEED_LIMIT_ICON_ENABLED(10, "setSpeedLimitIconEnabled"),
2928
SET_ZOOM_LEVEL(11, "setZoomLevel"),

android/src/main/java/com/google/android/react/navsdk/NavViewManager.java

Lines changed: 234 additions & 82 deletions
Large diffs are not rendered by default.

android/src/main/java/com/google/android/react/navsdk/NavViewModule.java

Lines changed: 21 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -160,32 +160,29 @@ public void isMyLocationEnabled(Integer viewId, final Promise promise) {
160160
public void addMarker(int viewId, ReadableMap markerOptionsMap, final Promise promise) {
161161
UiThreadUtil.runOnUiThread(
162162
() -> {
163-
if (mNavViewManager.getGoogleMap(viewId) != null) {
164-
Marker marker =
165-
mNavViewManager
166-
.getFragmentForViewId(viewId)
167-
.getMapController()
168-
.addMarker(markerOptionsMap.toHashMap());
169-
170-
promise.resolve(ObjectTranslationUtil.getMapFromMarker(marker));
163+
IMapViewFragment fragment = mNavViewManager.getFragmentForViewId(viewId);
164+
if (fragment == null) {
165+
promise.reject(JsErrors.NO_MAP_ERROR_CODE, JsErrors.NO_MAP_ERROR_MESSAGE);
166+
return;
171167
}
168+
169+
Marker marker = fragment.getMapController().addMarker(markerOptionsMap.toHashMap());
170+
promise.resolve(ObjectTranslationUtil.getMapFromMarker(marker));
172171
});
173172
}
174173

175174
@ReactMethod
176175
public void addPolyline(int viewId, ReadableMap polylineOptionsMap, final Promise promise) {
177176
UiThreadUtil.runOnUiThread(
178177
() -> {
179-
if (mNavViewManager.getGoogleMap(viewId) == null) {
178+
IMapViewFragment fragment = mNavViewManager.getFragmentForViewId(viewId);
179+
if (fragment == null) {
180180
promise.reject(JsErrors.NO_MAP_ERROR_CODE, JsErrors.NO_MAP_ERROR_MESSAGE);
181181
return;
182182
}
183-
Polyline polyline =
184-
mNavViewManager
185-
.getFragmentForViewId(viewId)
186-
.getMapController()
187-
.addPolyline(polylineOptionsMap.toHashMap());
188183

184+
Polyline polyline =
185+
fragment.getMapController().addPolyline(polylineOptionsMap.toHashMap());
189186
promise.resolve(ObjectTranslationUtil.getMapFromPolyline(polyline));
190187
});
191188
}
@@ -194,16 +191,13 @@ public void addPolyline(int viewId, ReadableMap polylineOptionsMap, final Promis
194191
public void addPolygon(int viewId, ReadableMap polygonOptionsMap, final Promise promise) {
195192
UiThreadUtil.runOnUiThread(
196193
() -> {
197-
if (mNavViewManager.getGoogleMap(viewId) == null) {
194+
IMapViewFragment fragment = mNavViewManager.getFragmentForViewId(viewId);
195+
if (fragment == null) {
198196
promise.reject(JsErrors.NO_MAP_ERROR_CODE, JsErrors.NO_MAP_ERROR_MESSAGE);
199197
return;
200198
}
201-
Polygon polygon =
202-
mNavViewManager
203-
.getFragmentForViewId(viewId)
204-
.getMapController()
205-
.addPolygon(polygonOptionsMap.toHashMap());
206199

200+
Polygon polygon = fragment.getMapController().addPolygon(polygonOptionsMap.toHashMap());
207201
promise.resolve(ObjectTranslationUtil.getMapFromPolygon(polygon));
208202
});
209203
}
@@ -212,16 +206,13 @@ public void addPolygon(int viewId, ReadableMap polygonOptionsMap, final Promise
212206
public void addCircle(int viewId, ReadableMap circleOptionsMap, final Promise promise) {
213207
UiThreadUtil.runOnUiThread(
214208
() -> {
215-
if (mNavViewManager.getGoogleMap(viewId) == null) {
209+
IMapViewFragment fragment = mNavViewManager.getFragmentForViewId(viewId);
210+
if (fragment == null) {
216211
promise.reject(JsErrors.NO_MAP_ERROR_CODE, JsErrors.NO_MAP_ERROR_MESSAGE);
217212
return;
218213
}
219-
Circle circle =
220-
mNavViewManager
221-
.getFragmentForViewId(viewId)
222-
.getMapController()
223-
.addCircle(circleOptionsMap.toHashMap());
224214

215+
Circle circle = fragment.getMapController().addCircle(circleOptionsMap.toHashMap());
225216
promise.resolve(ObjectTranslationUtil.getMapFromCircle(circle));
226217
});
227218
}
@@ -230,16 +221,14 @@ public void addCircle(int viewId, ReadableMap circleOptionsMap, final Promise pr
230221
public void addGroundOverlay(int viewId, ReadableMap overlayOptionsMap, final Promise promise) {
231222
UiThreadUtil.runOnUiThread(
232223
() -> {
233-
if (mNavViewManager.getGoogleMap(viewId) == null) {
224+
IMapViewFragment fragment = mNavViewManager.getFragmentForViewId(viewId);
225+
if (fragment == null) {
234226
promise.reject(JsErrors.NO_MAP_ERROR_CODE, JsErrors.NO_MAP_ERROR_MESSAGE);
235227
return;
236228
}
237-
GroundOverlay overlay =
238-
mNavViewManager
239-
.getFragmentForViewId(viewId)
240-
.getMapController()
241-
.addGroundOverlay(overlayOptionsMap.toHashMap());
242229

230+
GroundOverlay overlay =
231+
fragment.getMapController().addGroundOverlay(overlayOptionsMap.toHashMap());
243232
promise.resolve(ObjectTranslationUtil.getMapFromGroundOverlay(overlay));
244233
});
245234
}

ios/react-native-navigation-sdk/NavModule.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,7 @@ - (void)showTermsAndConditionsDialog {
412412

413413
- (void)setDisplayOptionsToViews:(NSDictionary *)options {
414414
for (NavViewController *viewController in [NavViewModule sharedInstance]
415-
.viewControllers.allValues) {
415+
.viewControllers.objectEnumerator) {
416416
if (options[@"showDestinationMarkers"] != nil) {
417417
[viewController
418418
setShowDestinationMarkersEnabled:[options[@"showDestinationMarkers"] boolValue]];

ios/react-native-navigation-sdk/NavView.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@
3535
@property(nonatomic, copy) RCTDirectEventBlock onGroundOverlayClick;
3636
@property(nonatomic, copy) RCTDirectEventBlock onPromptVisibilityChanged;
3737

38+
// Cleanup block that will be called when the view is removed from superview
39+
@property(nonatomic, copy) void (^cleanupBlock)(NSNumber *reactTag);
40+
3841
- (NavViewController *)initializeViewControllerWithStylingOptions:(NSDictionary *)stylingOptions
3942
fragmentType:(FragmentType)fragmentType;
4043
- (NavViewController *)getViewController;

ios/react-native-navigation-sdk/NavView.m

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,4 +126,14 @@ - (void)handleGroundOverlayClick:(GMSGroundOverlay *)groundOverlay {
126126
}
127127
}
128128

129+
- (void)willMoveToSuperview:(UIView *)newSuperview {
130+
[super willMoveToSuperview:newSuperview];
131+
if (newSuperview == nil && _viewController && self.cleanupBlock) {
132+
// As newSuperview is nil, the view is being removed from its superview, call the cleanup block
133+
// provided by the view manager
134+
self.cleanupBlock(self.reactTag);
135+
_viewController = nil;
136+
}
137+
}
138+
129139
@end

ios/react-native-navigation-sdk/NavViewController.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@ typedef void (^OnStringResult)(NSString *result);
3030
typedef void (^OnBooleanResult)(BOOL result);
3131
typedef void (^OnDictionaryResult)(NSDictionary *_Nullable result);
3232
typedef void (^OnArrayResult)(NSArray *_Nullable result);
33-
- (instancetype)initWithWidth:(CGFloat)width height:(CGFloat)height;
34-
- (void)updateLayoutWithWidth:(CGFloat)width height:(CGFloat)height;
3533
- (void)setStylingOptions:(nonnull NSDictionary *)stylingOptions;
3634
- (void)getCameraPosition:(OnDictionaryResult)completionBlock;
3735
- (void)getMyLocation:(OnDictionaryResult)completionBlock;

ios/react-native-navigation-sdk/NavViewModule.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
NS_ASSUME_NONNULL_BEGIN
2121

2222
@interface NavViewModule : NSObject <RCTBridgeModule>
23-
@property(nonatomic, strong) NSMutableDictionary<NSNumber *, NavViewController *> *viewControllers;
23+
@property(nonatomic, strong) NSMapTable<NSNumber *, NavViewController *> *viewControllers;
2424

2525
- (void)attachViewsToNavigationSession:(GMSNavigationSession *)session;
2626
- (void)informPromptVisibilityChange:(BOOL)visible;

ios/react-native-navigation-sdk/NavViewModule.m

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,25 +38,25 @@ + (instancetype)sharedInstance {
3838
}
3939

4040
- (void)attachViewsToNavigationSession:(GMSNavigationSession *)session {
41-
for (NavViewController *viewController in self.viewControllers.allValues) {
41+
for (NavViewController *viewController in self.viewControllers.objectEnumerator) {
4242
[viewController attachToNavigationSession:session];
4343
}
4444
}
4545

4646
- (void)informPromptVisibilityChange:(BOOL)visible {
47-
for (NavViewController *viewController in self.viewControllers.allValues) {
47+
for (NavViewController *viewController in self.viewControllers.objectEnumerator) {
4848
[viewController onPromptVisibilityChange:visible];
4949
}
5050
}
5151

5252
- (void)setTravelMode:(GMSNavigationTravelMode)travelMode {
53-
for (NavViewController *viewController in self.viewControllers.allValues) {
53+
for (NavViewController *viewController in self.viewControllers.objectEnumerator) {
5454
[viewController setTravelMode:travelMode];
5555
}
5656
}
5757

5858
- (NavViewController *)getViewControllerForTag:(NSNumber *)reactTag {
59-
NavViewController *viewController = self.viewControllers[reactTag];
59+
NavViewController *viewController = [self.viewControllers objectForKey:reactTag];
6060
return viewController;
6161
}
6262

0 commit comments

Comments
 (0)