Browse Source

Ensure component view is not created by mergeOptions (#6102)

When mergeOptions is called before a view is created or after it's destroyed, don't attempt to create the view.

Fixes #6097
Guy Carmeli 4 years ago
parent
commit
111df5a3ba
No account linked to committer's email address

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

96
     @Override
96
     @Override
97
     public void mergeOptions(Options options) {
97
     public void mergeOptions(Options options) {
98
         if (options == Options.EMPTY) return;
98
         if (options == Options.EMPTY) return;
99
-        presenter.mergeOptions(getView(), options);
99
+        if (isViewShown()) presenter.mergeOptions(getView(), options);
100
         super.mergeOptions(options);
100
         super.mergeOptions(options);
101
     }
101
     }
102
 
102
 

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

326
 
326
 
327
     public boolean isViewShown() {
327
     public boolean isViewShown() {
328
         return !isDestroyed &&
328
         return !isDestroyed &&
329
-               getView().isShown() &&
330
                view != null &&
329
                view != null &&
330
+               view.isShown() &&
331
                isRendered();
331
                isRendered();
332
     }
332
     }
333
 
333
 

+ 9
- 3
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/ComponentViewControllerTest.java View File

21
 import static org.mockito.Mockito.spy;
21
 import static org.mockito.Mockito.spy;
22
 import static org.mockito.Mockito.times;
22
 import static org.mockito.Mockito.times;
23
 import static org.mockito.Mockito.verify;
23
 import static org.mockito.Mockito.verify;
24
+import static org.mockito.Mockito.verifyZeroInteractions;
24
 import static org.mockito.Mockito.when;
25
 import static org.mockito.Mockito.when;
25
 
26
 
26
 public class ComponentViewControllerTest extends BaseTest {
27
 public class ComponentViewControllerTest extends BaseTest {
40
         parent = TestUtils.newStackController(activity).build();
41
         parent = TestUtils.newStackController(activity).build();
41
         Presenter presenter = new Presenter(activity, new Options());
42
         Presenter presenter = new Presenter(activity, new Options());
42
         this.presenter = spy(new ComponentPresenter(Options.EMPTY));
43
         this.presenter = spy(new ComponentPresenter(Options.EMPTY));
43
-        uut = new ComponentViewController(activity, new ChildControllersRegistry(), "componentId1", "componentName", (activity1, componentId, componentName) -> view, new Options(), presenter, this.presenter) {
44
+        uut = spy(new ComponentViewController(activity, new ChildControllersRegistry(), "componentId1", "componentName", (activity1, componentId, componentName) -> view, new Options(), presenter, this.presenter) {
44
             @Override
45
             @Override
45
             public Options resolveCurrentOptions(Options defaultOptions) {
46
             public Options resolveCurrentOptions(Options defaultOptions) {
46
                 return resolvedOptions;
47
                 return resolvedOptions;
47
             }
48
             }
48
-        };
49
+        });
49
         uut.setParentController(parent);
50
         uut.setParentController(parent);
50
         parent.ensureViewIsCreated();
51
         parent.ensureViewIsCreated();
51
     }
52
     }
117
     }
118
     }
118
 
119
 
119
     @Test
120
     @Test
120
-    public void mergeOptions_delegatesToPresenter() {
121
+    public void mergeOptions_delegatesToPresenterIfViewIsNotShown() {
121
         Options options = new Options();
122
         Options options = new Options();
123
+        assertThat(uut.isViewShown()).isFalse();
124
+        uut.mergeOptions(options);
125
+        verifyZeroInteractions(presenter);
126
+
127
+        when(uut.isViewShown()).thenReturn(true);
122
         uut.mergeOptions(options);
128
         uut.mergeOptions(options);
123
         verify(presenter).mergeOptions(uut.getView(), options);
129
         verify(presenter).mergeOptions(uut.getView(), options);
124
     }
130
     }

+ 8
- 1
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/ViewControllerTest.java View File

1
 package com.reactnativenavigation.viewcontrollers;
1
 package com.reactnativenavigation.viewcontrollers;
2
 
2
 
3
 import android.app.Activity;
3
 import android.app.Activity;
4
-import androidx.coordinatorlayout.widget.CoordinatorLayout;
5
 import android.view.View;
4
 import android.view.View;
6
 import android.view.ViewGroup;
5
 import android.view.ViewGroup;
7
 import android.view.ViewParent;
6
 import android.view.ViewParent;
27
 
26
 
28
 import java.lang.reflect.Field;
27
 import java.lang.reflect.Field;
29
 
28
 
29
+import androidx.coordinatorlayout.widget.CoordinatorLayout;
30
+
30
 import static org.assertj.core.api.Java6Assertions.assertThat;
31
 import static org.assertj.core.api.Java6Assertions.assertThat;
31
 import static org.mockito.Mockito.mock;
32
 import static org.mockito.Mockito.mock;
32
 import static org.mockito.Mockito.spy;
33
 import static org.mockito.Mockito.spy;
183
         verify(spy, times(1)).onViewAppeared();
184
         verify(spy, times(1)).onViewAppeared();
184
     }
185
     }
185
 
186
 
187
+    @Test
188
+    public void isViewShown_doesNotCreateView() {
189
+        assertThat(uut.isViewShown()).isFalse();
190
+        assertThat(uut.view).isNull();
191
+    }
192
+
186
     @Test
193
     @Test
187
     public void onDisappear_WhenNotShown_AfterOnAppearWasCalled() {
194
     public void onDisappear_WhenNotShown_AfterOnAppearWasCalled() {
188
         ViewController spy = spy(uut);
195
         ViewController spy = spy(uut);