Просмотр исходного кода

Address react conditions around ViewController.destroy (#5162)

Closes #5157
Guy Carmeli 5 лет назад
Родитель
Сommit
f2e46ea4e7
No account linked to committer's email address

+ 1
- 0
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/ChildController.java Просмотреть файл

@@ -68,6 +68,7 @@ public abstract class ChildController<T extends ViewGroup> extends ViewControlle
68 68
             performOnParentController(parent -> parent.onChildDestroyed((Component) getView()));
69 69
         }
70 70
         super.destroy();
71
+        childRegistry.onChildDestroyed(this);
71 72
     }
72 73
 
73 74
     protected boolean isRoot() {

+ 4
- 0
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/ChildControllersRegistry.java Просмотреть файл

@@ -25,4 +25,8 @@ public class ChildControllersRegistry {
25 25
     public int size() {
26 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 Просмотреть файл

@@ -268,7 +268,7 @@ public abstract class ViewController<T extends ViewGroup> implements ViewTreeObs
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 Просмотреть файл

@@ -58,6 +58,7 @@ public class StackController extends ParentController<StackLayout> {
58 58
     @Override
59 59
     public boolean isRendered() {
60 60
         if (isEmpty()) return false;
61
+        if (getCurrentChild().isDestroyed()) return false;
61 62
         ViewGroup currentChild = getCurrentChild().getView();
62 63
         if (currentChild instanceof Component) {
63 64
             return super.isRendered() && presenter.isRendered((Component) currentChild);
@@ -78,7 +79,7 @@ public class StackController extends ParentController<StackLayout> {
78 79
 
79 80
     @Override
80 81
     public void onAttachToParent() {
81
-        if (!isViewShown() && !isEmpty()) {
82
+        if (!isEmpty() && !getCurrentChild().isDestroyed() && !isViewShown()) {
82 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 Просмотреть файл

@@ -78,4 +78,10 @@ public class ChildControllerTest extends BaseTest {
78 78
         uut.mergeOptions(Options.EMPTY);
79 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 Просмотреть файл

@@ -44,4 +44,10 @@ public class ChildControllersRegistryTest extends BaseTest {
44 44
         verify(child1, times(1)).onViewBroughtToFront();
45 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 Просмотреть файл

@@ -1057,24 +1057,39 @@ public class StackControllerTest extends BaseTest {
1057 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 1075
     private void assertContainsOnlyId(String... ids) {
1061 1076
         assertThat(uut.size()).isEqualTo(ids.length);
1062 1077
         assertThat(uut.getChildControllers()).extracting((Extractor<ViewController, String>) ViewController::getId).containsOnly(ids);
1063 1078
     }
1064 1079
 
1065 1080
     private StackController createStack() {
1066
-        return createStack("stack", new ArrayList<>());
1081
+        return createStackBuilder("stack", new ArrayList<>()).build();
1067 1082
     }
1068 1083
 
1069 1084
     private StackController createStack(String id) {
1070
-        return createStack(id, new ArrayList<>());
1085
+        return createStackBuilder(id, new ArrayList<>()).build();
1071 1086
     }
1072 1087
 
1073 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 1093
         createTopBarController();
1079 1094
         return TestUtils.newStackController(activity)
1080 1095
                 .setChildren(children)
@@ -1083,8 +1098,7 @@ public class StackControllerTest extends BaseTest {
1083 1098
                 .setChildRegistry(childRegistry)
1084 1099
                 .setAnimator(animator)
1085 1100
                 .setStackPresenter(presenter)
1086
-                .setBackButtonHelper(backButtonHelper)
1087
-                .build();
1101
+                .setBackButtonHelper(backButtonHelper);
1088 1102
     }
1089 1103
 
1090 1104
     private void createTopBarController() {