Browse Source

Address react conditions around ViewController.destroy (#5162)

Closes #5157
Guy Carmeli 5 years ago
parent
commit
f2e46ea4e7
No account linked to committer's email address

+ 1
- 0
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/ChildController.java View File

68
             performOnParentController(parent -> parent.onChildDestroyed((Component) getView()));
68
             performOnParentController(parent -> parent.onChildDestroyed((Component) getView()));
69
         }
69
         }
70
         super.destroy();
70
         super.destroy();
71
+        childRegistry.onChildDestroyed(this);
71
     }
72
     }
72
 
73
 
73
     protected boolean isRoot() {
74
     protected boolean isRoot() {

+ 4
- 0
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/ChildControllersRegistry.java View File

25
     public int size() {
25
     public int size() {
26
         return children.size();
26
         return children.size();
27
     }
27
     }
28
+
29
+    public void onChildDestroyed(ChildController child) {
30
+        children.remove(child);
31
+    }
28
 }
32
 }

+ 1
- 1
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/ViewController.java View File

268
         }
268
         }
269
     }
269
     }
270
 
270
 
271
-    protected void onAttachToParent() {
271
+    public void onAttachToParent() {
272
 
272
 
273
     }
273
     }
274
 
274
 

+ 2
- 1
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/stack/StackController.java View File

58
     @Override
58
     @Override
59
     public boolean isRendered() {
59
     public boolean isRendered() {
60
         if (isEmpty()) return false;
60
         if (isEmpty()) return false;
61
+        if (getCurrentChild().isDestroyed()) return false;
61
         ViewGroup currentChild = getCurrentChild().getView();
62
         ViewGroup currentChild = getCurrentChild().getView();
62
         if (currentChild instanceof Component) {
63
         if (currentChild instanceof Component) {
63
             return super.isRendered() && presenter.isRendered((Component) currentChild);
64
             return super.isRendered() && presenter.isRendered((Component) currentChild);
78
 
79
 
79
     @Override
80
     @Override
80
     public void onAttachToParent() {
81
     public void onAttachToParent() {
81
-        if (!isViewShown() && !isEmpty()) {
82
+        if (!isEmpty() && !getCurrentChild().isDestroyed() && !isViewShown()) {
82
             presenter.applyChildOptions(resolveCurrentOptions(), (Component) getCurrentChild().getView());
83
             presenter.applyChildOptions(resolveCurrentOptions(), (Component) getCurrentChild().getView());
83
         }
84
         }
84
     }
85
     }

+ 6
- 0
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/child/ChildControllerTest.java View File

78
         uut.mergeOptions(Options.EMPTY);
78
         uut.mergeOptions(Options.EMPTY);
79
         verify(presenter, times(0)).mergeOptions(any(), any());
79
         verify(presenter, times(0)).mergeOptions(any(), any());
80
     }
80
     }
81
+
82
+    @Test
83
+    public void destroy() {
84
+        uut.destroy();
85
+        verify(childRegistry).onChildDestroyed(uut);
86
+    }
81
 }
87
 }

+ 6
- 0
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/child/ChildControllersRegistryTest.java View File

44
         verify(child1, times(1)).onViewBroughtToFront();
44
         verify(child1, times(1)).onViewBroughtToFront();
45
         assertThat(uut.size()).isOne();
45
         assertThat(uut.size()).isOne();
46
     }
46
     }
47
+
48
+    @Test
49
+    public void onChildDestroyed() {
50
+        child1.destroy();
51
+        assertThat(uut.size()).isEqualTo(0);
52
+    }
47
 }
53
 }

+ 20
- 6
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/stack/StackControllerTest.java View File

1057
         verify(presenter).applyChildOptions(any(), eq(component));
1057
         verify(presenter).applyChildOptions(any(), eq(component));
1058
     }
1058
     }
1059
 
1059
 
1060
+    @Test
1061
+    public void onAttachToParent_doesNotCrashWhenCalledAfterDestroy() {
1062
+        Robolectric.getForegroundThreadScheduler().pause();
1063
+        StackController spy = spy(createStack());
1064
+
1065
+        StackLayout view = spy.getView();
1066
+        spy.push(child1, new CommandListenerAdapter());
1067
+        activity.setContentView(view);
1068
+
1069
+        child1.destroy();
1070
+        ShadowLooper.idleMainLooper();
1071
+
1072
+        verify(spy).onAttachToParent();
1073
+    }
1074
+
1060
     private void assertContainsOnlyId(String... ids) {
1075
     private void assertContainsOnlyId(String... ids) {
1061
         assertThat(uut.size()).isEqualTo(ids.length);
1076
         assertThat(uut.size()).isEqualTo(ids.length);
1062
         assertThat(uut.getChildControllers()).extracting((Extractor<ViewController, String>) ViewController::getId).containsOnly(ids);
1077
         assertThat(uut.getChildControllers()).extracting((Extractor<ViewController, String>) ViewController::getId).containsOnly(ids);
1063
     }
1078
     }
1064
 
1079
 
1065
     private StackController createStack() {
1080
     private StackController createStack() {
1066
-        return createStack("stack", new ArrayList<>());
1081
+        return createStackBuilder("stack", new ArrayList<>()).build();
1067
     }
1082
     }
1068
 
1083
 
1069
     private StackController createStack(String id) {
1084
     private StackController createStack(String id) {
1070
-        return createStack(id, new ArrayList<>());
1085
+        return createStackBuilder(id, new ArrayList<>()).build();
1071
     }
1086
     }
1072
 
1087
 
1073
     private StackController createStack(List<ViewController> children) {
1088
     private StackController createStack(List<ViewController> children) {
1074
-        return createStack("stack", children);
1089
+        return createStackBuilder("stack", children).build();
1075
     }
1090
     }
1076
 
1091
 
1077
-    private StackController createStack(String id, List<ViewController> children) {
1092
+    private StackControllerBuilder createStackBuilder(String id, List<ViewController> children) {
1078
         createTopBarController();
1093
         createTopBarController();
1079
         return TestUtils.newStackController(activity)
1094
         return TestUtils.newStackController(activity)
1080
                 .setChildren(children)
1095
                 .setChildren(children)
1083
                 .setChildRegistry(childRegistry)
1098
                 .setChildRegistry(childRegistry)
1084
                 .setAnimator(animator)
1099
                 .setAnimator(animator)
1085
                 .setStackPresenter(presenter)
1100
                 .setStackPresenter(presenter)
1086
-                .setBackButtonHelper(backButtonHelper)
1087
-                .build();
1101
+                .setBackButtonHelper(backButtonHelper);
1088
     }
1102
     }
1089
 
1103
 
1090
     private void createTopBarController() {
1104
     private void createTopBarController() {