Browse Source

android controller lifecycle #1065

Daniel Zlotin 7 years ago
parent
commit
5810865b61

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

@@ -3,11 +3,28 @@ package com.reactnativenavigation.viewcontrollers;
3 3
 import android.app.Activity;
4 4
 import android.support.annotation.Nullable;
5 5
 import android.view.View;
6
+import android.view.ViewTreeObserver;
6 7
 
7 8
 public abstract class ViewController {
9
+	public interface LifecycleListener {
10
+		void onCreate(ViewController viewController);
11
+
12
+		void onStart(ViewController viewController);
13
+
14
+		void onStop(ViewController viewController);
15
+
16
+		void onDestroy(ViewController viewController);
17
+	}
18
+
19
+	private enum LifecycleState {
20
+		Created, Started, Stopped, Destroyed
21
+	}
22
+
8 23
 	private final Activity activity;
9 24
 	private View view;
10 25
 	private StackController stackController;
26
+	private LifecycleState lifecycleState;
27
+	private LifecycleListener lifecycleListener;
11 28
 
12 29
 	public ViewController(Activity activity) {
13 30
 		this.activity = activity;
@@ -34,7 +51,32 @@ public abstract class ViewController {
34 51
 
35 52
 	public View getView() {
36 53
 		if (view == null) {
37
-			view = onCreateView();
54
+			view = createView();
55
+		}
56
+		return view;
57
+	}
58
+
59
+	public void setLifecycleListener(LifecycleListener lifecycleListener) {
60
+		this.lifecycleListener = lifecycleListener;
61
+	}
62
+
63
+	private View createView() {
64
+		View view = onCreateView();
65
+		lifecycleState = LifecycleState.Created;
66
+		view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
67
+			@Override
68
+			public boolean onPreDraw() {
69
+				if (lifecycleListener != null) {
70
+					if (lifecycleState != LifecycleState.Started) {
71
+						lifecycleState = LifecycleState.Started;
72
+						lifecycleListener.onStart(ViewController.this);
73
+					}
74
+				}
75
+				return true;
76
+			}
77
+		});
78
+		if (lifecycleListener != null) {
79
+			lifecycleListener.onCreate(this);
38 80
 		}
39 81
 		return view;
40 82
 	}

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

@@ -9,6 +9,10 @@ import com.reactnativenavigation.mocks.SimpleViewController;
9 9
 import org.junit.Test;
10 10
 
11 11
 import static org.assertj.core.api.Java6Assertions.assertThat;
12
+import static org.mockito.Mockito.mock;
13
+import static org.mockito.Mockito.times;
14
+import static org.mockito.Mockito.verify;
15
+import static org.mockito.Mockito.verifyZeroInteractions;
12 16
 
13 17
 public class ViewControllerTest extends BaseTest {
14 18
 
@@ -56,4 +60,34 @@ public class ViewControllerTest extends BaseTest {
56 60
 	public void handleBackDefaultFalse() throws Exception {
57 61
 		assertThat(uut.handleBack()).isFalse();
58 62
 	}
63
+
64
+	public static class LifecycleTest extends BaseTest {
65
+		private ViewController controller;
66
+		private ViewController.LifecycleListener uut;
67
+
68
+		@Override
69
+		public void beforeEach() {
70
+			super.beforeEach();
71
+			Activity activity = newActivity();
72
+			controller = new SimpleViewController(activity, "controller");
73
+			uut = mock(ViewController.LifecycleListener.class);
74
+			controller.setLifecycleListener(uut);
75
+		}
76
+
77
+		@Test
78
+		public void onCreateView_CalledAsSoonAsPossible() throws Exception {
79
+			verifyZeroInteractions(uut);
80
+			controller.getView();
81
+			verify(uut, times(1)).onCreate(controller);
82
+		}
83
+
84
+		@Test
85
+		public void onStart_CalledBeforeFirstDraw() throws Exception {
86
+			verifyZeroInteractions(uut);
87
+			controller.getView().getViewTreeObserver().dispatchOnPreDraw();
88
+			controller.getView().getViewTreeObserver().dispatchOnPreDraw();
89
+			verify(uut, times(1)).onStart(controller);
90
+		}
91
+	}
92
+
59 93
 }