浏览代码

Destroy views when activity is destroyed and reloaded

Guy Carmeli 6 年前
父节点
当前提交
096481e496

+ 18
- 10
lib/android/app/src/main/java/com/reactnativenavigation/NavigationActivity.java 查看文件

@@ -6,37 +6,41 @@ import android.support.v7.app.AppCompatActivity;
6 6
 import android.view.KeyEvent;
7 7
 
8 8
 import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
9
+import com.reactnativenavigation.presentation.OverlayManager;
10
+import com.reactnativenavigation.react.ReactGateway;
9 11
 import com.reactnativenavigation.utils.CommandListenerAdapter;
10 12
 import com.reactnativenavigation.viewcontrollers.Navigator;
11 13
 
12 14
 public class NavigationActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler {
13
-	private Navigator navigator;
15
+	protected Navigator navigator;
14 16
 
15 17
 	@Override
16 18
 	protected void onCreate(@Nullable Bundle savedInstanceState) {
17 19
 		super.onCreate(savedInstanceState);
18
-		app().getReactGateway().onActivityCreated(this);
19
-		navigator = new Navigator(this);
20
+		navigator = new Navigator(this, new OverlayManager());
21
+		getReactGateway().onActivityCreated(this);
22
+		getReactGateway().addReloadListener(navigator);
20 23
 		setContentView(navigator.getView());
21 24
 	}
22 25
 
23
-	@Override
26
+    @Override
24 27
 	protected void onResume() {
25 28
 		super.onResume();
26
-		app().getReactGateway().onActivityResumed(this);
29
+		getReactGateway().onActivityResumed(this);
27 30
 	}
28 31
 
29 32
 	@Override
30 33
 	protected void onPause() {
31 34
 		super.onPause();
32
-		app().getReactGateway().onActivityPaused(this);
35
+		getReactGateway().onActivityPaused(this);
33 36
 	}
34 37
 
35 38
 	@Override
36 39
 	protected void onDestroy() {
37 40
 		super.onDestroy();
38 41
 		navigator.destroy();
39
-		app().getReactGateway().onActivityDestroyed(this);
42
+		getReactGateway().removeReloadListener(navigator);
43
+		getReactGateway().onActivityDestroyed(this);
40 44
 	}
41 45
 
42 46
 	@Override
@@ -48,19 +52,23 @@ public class NavigationActivity extends AppCompatActivity implements DefaultHard
48 52
 
49 53
 	@Override
50 54
 	public void onBackPressed() {
51
-		app().getReactGateway().onBackPressed();
55
+		getReactGateway().onBackPressed();
52 56
 	}
53 57
 
54 58
 	@Override
55 59
 	public boolean onKeyUp(final int keyCode, final KeyEvent event) {
56
-		return app().getReactGateway().onKeyUp(keyCode) || super.onKeyUp(keyCode, event);
60
+		return getReactGateway().onKeyUp(keyCode) || super.onKeyUp(keyCode, event);
57 61
 	}
58 62
 
63
+    public ReactGateway getReactGateway() {
64
+        return app().getReactGateway();
65
+    }
66
+
59 67
 	private NavigationApplication app() {
60 68
 		return (NavigationApplication) getApplication();
61 69
 	}
62 70
 
63
-	public Navigator getNavigator() {
71
+    public Navigator getNavigator() {
64 72
 		return navigator;
65 73
 	}
66 74
 }

+ 23
- 8
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/Navigator.java 查看文件

@@ -14,6 +14,7 @@ import com.reactnativenavigation.anim.NavigationAnimator;
14 14
 import com.reactnativenavigation.parse.Options;
15 15
 import com.reactnativenavigation.presentation.NavigationOptionsListener;
16 16
 import com.reactnativenavigation.presentation.OverlayManager;
17
+import com.reactnativenavigation.react.JsDevReloadHandler;
17 18
 import com.reactnativenavigation.utils.CommandListenerAdapter;
18 19
 import com.reactnativenavigation.utils.CompatUtils;
19 20
 import com.reactnativenavigation.viewcontrollers.modal.ModalPresenter;
@@ -22,7 +23,7 @@ import com.reactnativenavigation.viewcontrollers.modal.ModalStack;
22 23
 import java.util.Collection;
23 24
 import java.util.Collections;
24 25
 
25
-public class Navigator extends ParentController {
26
+public class Navigator extends ParentController implements JsDevReloadHandler.ReloadListener {
26 27
 
27 28
     public interface CommandListener {
28 29
         void onSuccess(String childId);
@@ -34,12 +35,13 @@ public class Navigator extends ParentController {
34 35
     private ViewController root;
35 36
     private FrameLayout rootLayout;
36 37
     private FrameLayout contentLayout;
37
-    private OverlayManager overlayManager = new OverlayManager();
38
+    private final OverlayManager overlayManager;
38 39
     private Options defaultOptions = new Options();
39 40
 
40
-    public Navigator(final Activity activity) {
41
+    public Navigator(final Activity activity, OverlayManager overlayManager) {
41 42
         super(activity, "navigator" + CompatUtils.generateViewId(), new Options());
42 43
         modalStack = new ModalStack(new ModalPresenter(new ModalAnimator(activity)));
44
+        this.overlayManager = overlayManager;
43 45
     }
44 46
 
45 47
     public FrameLayout getContentLayout() {
@@ -68,22 +70,35 @@ public class Navigator extends ParentController {
68 70
         return modalStack.handleBack(listener, root);
69 71
     }
70 72
 
73
+    @Override
74
+    public void onReload() {
75
+        destroyViews();
76
+    }
77
+
71 78
     @Override
72 79
     public void destroy() {
73
-        modalStack.dismissAllModals(new CommandListenerAdapter(), root);
80
+        destroyViews();
74 81
         super.destroy();
75 82
     }
76 83
 
84
+    private void destroyViews() {
85
+        destroyRoot();
86
+        overlayManager.destroy();
87
+        modalStack.dismissAllModals(new CommandListenerAdapter(), root);
88
+    }
89
+
90
+    private void destroyRoot() {
91
+        if (root != null) root.destroy();
92
+        root = null;
93
+    }
94
+
77 95
     @Override
78 96
     public void sendOnNavigationButtonPressed(String buttonId) {
79 97
 
80 98
     }
81 99
 
82 100
     public void setRoot(final ViewController viewController, Promise promise) {
83
-        if (root != null) {
84
-            root.destroy();
85
-        }
86
-
101
+        destroyRoot();
87 102
         root = viewController;
88 103
         contentLayout.addView(viewController.getView());
89 104
         if (viewController.options.animations.startApp.hasValue()) {

+ 5
- 0
lib/android/app/src/test/java/com/reactnativenavigation/BaseTest.java 查看文件

@@ -11,6 +11,7 @@ import com.reactnativenavigation.viewcontrollers.ViewController;
11 11
 import org.junit.*;
12 12
 import org.junit.runner.*;
13 13
 import org.robolectric.*;
14
+import org.robolectric.android.controller.ActivityController;
14 15
 import org.robolectric.annotation.*;
15 16
 
16 17
 import static org.assertj.core.api.Java6Assertions.*;
@@ -32,6 +33,10 @@ public abstract class BaseTest {
32 33
         return Robolectric.setupActivity(AppCompatActivity.class);
33 34
     }
34 35
 
36
+    public <T extends AppCompatActivity> ActivityController<T> newActivityController(Class<T> clazz) {
37
+        return Robolectric.buildActivity(clazz);
38
+    }
39
+
35 40
     public void assertIsChild(ViewGroup parent, View child) {
36 41
         assertThat(parent).isNotNull();
37 42
         assertThat(child).isNotNull();

+ 18
- 0
lib/android/app/src/test/java/com/reactnativenavigation/TestActivity.java 查看文件

@@ -0,0 +1,18 @@
1
+package com.reactnativenavigation;
2
+
3
+import com.reactnativenavigation.react.ReactGateway;
4
+import com.reactnativenavigation.viewcontrollers.Navigator;
5
+
6
+import org.mockito.Mockito;
7
+
8
+public class TestActivity extends NavigationActivity {
9
+
10
+    @Override
11
+    public ReactGateway getReactGateway() {
12
+        return Mockito.mock(ReactGateway.class);
13
+    }
14
+
15
+    public void setNavigator(Navigator navigator) {
16
+        this.navigator = navigator;
17
+    }
18
+}

+ 38
- 5
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/NavigatorTest.java 查看文件

@@ -1,9 +1,9 @@
1 1
 package com.reactnativenavigation.viewcontrollers;
2 2
 
3
-import android.app.Activity;
4 3
 import android.support.annotation.NonNull;
5 4
 
6 5
 import com.reactnativenavigation.BaseTest;
6
+import com.reactnativenavigation.TestActivity;
7 7
 import com.reactnativenavigation.mocks.ImageLoaderMock;
8 8
 import com.reactnativenavigation.mocks.MockPromise;
9 9
 import com.reactnativenavigation.mocks.SimpleComponentViewController;
@@ -14,6 +14,7 @@ import com.reactnativenavigation.mocks.TopBarButtonCreatorMock;
14 14
 import com.reactnativenavigation.parse.Options;
15 15
 import com.reactnativenavigation.parse.params.Bool;
16 16
 import com.reactnativenavigation.parse.params.Text;
17
+import com.reactnativenavigation.presentation.OverlayManager;
17 18
 import com.reactnativenavigation.utils.CommandListenerAdapter;
18 19
 import com.reactnativenavigation.utils.CompatUtils;
19 20
 import com.reactnativenavigation.utils.ImageLoader;
@@ -23,6 +24,8 @@ import com.reactnativenavigation.viewcontrollers.topbar.TopBarBackgroundViewCont
23 24
 import com.reactnativenavigation.viewcontrollers.topbar.TopBarController;
24 25
 
25 26
 import org.junit.Test;
27
+import org.mockito.Mockito;
28
+import org.robolectric.android.controller.ActivityController;
26 29
 
27 30
 import java.util.Arrays;
28 31
 
@@ -36,7 +39,7 @@ import static org.mockito.Mockito.verify;
36 39
 import static org.mockito.Mockito.when;
37 40
 
38 41
 public class NavigatorTest extends BaseTest {
39
-    private Activity activity;
42
+    private TestActivity activity;
40 43
     private Navigator uut;
41 44
     private StackController parentController;
42 45
     private SimpleViewController child1;
@@ -46,13 +49,19 @@ public class NavigatorTest extends BaseTest {
46 49
     private ViewController child5;
47 50
     private Options tabOptions = OptionHelper.createBottomTabOptions();
48 51
     private ImageLoader imageLoaderMock;
52
+    private ActivityController<TestActivity> activityController;
53
+    private OverlayManager overlayManager;
49 54
 
50 55
     @Override
51 56
     public void beforeEach() {
52 57
         super.beforeEach();
58
+        overlayManager = Mockito.mock(OverlayManager.class);
53 59
         imageLoaderMock = ImageLoaderMock.mock();
54
-        activity = newActivity();
55
-        uut = new Navigator(activity);
60
+        activityController = newActivityController(TestActivity.class);
61
+        activity = activityController.create().get();
62
+        uut = new Navigator(activity, overlayManager);
63
+        activity.setNavigator(uut);
64
+
56 65
         parentController = spy(newStack());
57 66
         parentController.ensureViewIsCreated();
58 67
         child1 = new SimpleViewController(activity, "child1", tabOptions);
@@ -61,6 +70,8 @@ public class NavigatorTest extends BaseTest {
61 70
         child4 = new SimpleViewController(activity, "child4", tabOptions);
62 71
         child5 = new SimpleViewController(activity, "child5", tabOptions);
63 72
         activity.setContentView(uut.getView());
73
+
74
+        activityController.visible();
64 75
     }
65 76
 
66 77
     @Test
@@ -80,7 +91,7 @@ public class NavigatorTest extends BaseTest {
80 91
     @Test
81 92
     public void hasUniqueId() {
82 93
         assertThat(uut.getId()).startsWith("navigator");
83
-        assertThat(new Navigator(activity).getId()).isNotEqualTo(uut.getId());
94
+        assertThat(new Navigator(activity, overlayManager).getId()).isNotEqualTo(uut.getId());
84 95
     }
85 96
 
86 97
     @Test
@@ -447,4 +458,26 @@ public class NavigatorTest extends BaseTest {
447 458
         });
448 459
     }
449 460
 
461
+    @Test
462
+    public void destroy_destroyedRoot() {
463
+        parentController.options.animations.startApp.enable = new Bool(false);
464
+        uut.setRoot(parentController, new MockPromise());
465
+        activityController.destroy();
466
+        verify(parentController, times(1)).destroy();
467
+    }
468
+
469
+    @Test
470
+    public void destroy_destroyOverlayManager() {
471
+        uut.setRoot(parentController, new MockPromise());
472
+        activityController.destroy();
473
+        verify(overlayManager, times(1)).destroy();
474
+    }
475
+
476
+    @Test
477
+    public void reload_navigatorIsDestroyedOnReload() {
478
+        uut.setRoot(parentController, new MockPromise());
479
+        uut.onReload();
480
+        verify(parentController, times(1)).destroy();
481
+        verify(overlayManager, times(1)).destroy();
482
+    }
450 483
 }