Daniel Zlotin 7 years ago
parent
commit
a607f8cbc0

+ 1
- 1
lib/android/app/src/main/java/com/reactnativenavigation/layout/impl/ReactRootViewController.java View File

46
 	}
46
 	}
47
 
47
 
48
 	@Override
48
 	@Override
49
-	protected View onCreateView() {
49
+	protected View createView() {
50
 		ReactRootView reactRootView = new ReactRootView(getActivity());
50
 		ReactRootView reactRootView = new ReactRootView(getActivity());
51
 		reactRootView.addOnAttachStateChangeListener(this);
51
 		reactRootView.addOnAttachStateChangeListener(this);
52
 		Bundle opts = new Bundle();
52
 		Bundle opts = new Bundle();

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

77
 	}
77
 	}
78
 
78
 
79
 	@Override
79
 	@Override
80
-	protected ViewGroup onCreateView() {
80
+	protected ViewGroup createView() {
81
 		return new FrameLayout(getActivity());
81
 		return new FrameLayout(getActivity());
82
 	}
82
 	}
83
 
83
 

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

5
 import android.view.View;
5
 import android.view.View;
6
 import android.view.ViewTreeObserver;
6
 import android.view.ViewTreeObserver;
7
 
7
 
8
+import java.util.concurrent.atomic.AtomicReference;
9
+
8
 public abstract class ViewController {
10
 public abstract class ViewController {
9
 	public interface LifecycleListener {
11
 	public interface LifecycleListener {
10
-		void onCreate(ViewController viewController);
12
+		void onCreate();
11
 
13
 
12
-		void onStart(ViewController viewController);
14
+		void onStart();
13
 
15
 
14
-		void onStop(ViewController viewController);
16
+		void onStop();
15
 
17
 
16
-		void onDestroy(ViewController viewController);
18
+		void onDestroy();
17
 	}
19
 	}
18
 
20
 
19
 	private enum LifecycleState {
21
 	private enum LifecycleState {
23
 	private final Activity activity;
25
 	private final Activity activity;
24
 	private View view;
26
 	private View view;
25
 	private StackController stackController;
27
 	private StackController stackController;
26
-	private LifecycleState lifecycleState;
28
+	private AtomicReference<LifecycleState> lifecycleState = new AtomicReference<>(LifecycleState.Destroyed);
27
 	private LifecycleListener lifecycleListener;
29
 	private LifecycleListener lifecycleListener;
28
 
30
 
29
 	public ViewController(Activity activity) {
31
 	public ViewController(Activity activity) {
30
 		this.activity = activity;
32
 		this.activity = activity;
31
 	}
33
 	}
32
 
34
 
33
-	protected abstract View onCreateView();
35
+	protected abstract View createView();
34
 
36
 
35
 	public boolean handleBack() {
37
 	public boolean handleBack() {
36
 		return false;
38
 		return false;
52
 	public View getView() {
54
 	public View getView() {
53
 		if (view == null) {
55
 		if (view == null) {
54
 			view = createView();
56
 			view = createView();
57
+			attachLifecycle();
55
 		}
58
 		}
56
 		return view;
59
 		return view;
57
 	}
60
 	}
60
 		this.lifecycleListener = lifecycleListener;
63
 		this.lifecycleListener = lifecycleListener;
61
 	}
64
 	}
62
 
65
 
63
-	private View createView() {
64
-		View view = onCreateView();
65
-		lifecycleState = LifecycleState.Created;
66
-		view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
66
+	private void attachLifecycle() {
67
+		view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
67
 			@Override
68
 			@Override
68
-			public boolean onPreDraw() {
69
-				if (lifecycleListener != null) {
70
-					if (lifecycleState != LifecycleState.Started) {
71
-						lifecycleState = LifecycleState.Started;
72
-						lifecycleListener.onStart(ViewController.this);
69
+			public void onGlobalLayout() {
70
+				if (lifecycleListener == null) {
71
+					return;
72
+				}
73
+				if (view.getVisibility() == View.VISIBLE) {
74
+					if (lifecycleState.compareAndSet(LifecycleState.Created, LifecycleState.Started)) {
75
+						lifecycleListener.onStart();
76
+					}
77
+				} else {
78
+					if (lifecycleState.compareAndSet(LifecycleState.Started, LifecycleState.Stopped)) {
79
+						lifecycleListener.onStop();
73
 					}
80
 					}
74
 				}
81
 				}
75
-				return true;
76
 			}
82
 			}
77
 		});
83
 		});
84
+		lifecycleState.set(LifecycleState.Created);
78
 		if (lifecycleListener != null) {
85
 		if (lifecycleListener != null) {
79
-			lifecycleListener.onCreate(this);
86
+			lifecycleListener.onCreate();
80
 		}
87
 		}
81
-		return view;
82
 	}
88
 	}
83
 }
89
 }

+ 1
- 1
lib/android/app/src/test/java/com/reactnativenavigation/mocks/SimpleViewController.java View File

14
 	}
14
 	}
15
 
15
 
16
 	@Override
16
 	@Override
17
-	protected View onCreateView() {
17
+	protected View createView() {
18
 		return new View(getActivity());
18
 		return new View(getActivity());
19
 	}
19
 	}
20
 
20
 

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

41
 		final View otherView = new View(activity);
41
 		final View otherView = new View(activity);
42
 		ViewController myController = new ViewController(activity) {
42
 		ViewController myController = new ViewController(activity) {
43
 			@Override
43
 			@Override
44
-			protected View onCreateView() {
44
+			protected View createView() {
45
 				return otherView;
45
 				return otherView;
46
 			}
46
 			}
47
 		};
47
 		};
78
 		public void onCreateView_CalledAsSoonAsPossible() throws Exception {
78
 		public void onCreateView_CalledAsSoonAsPossible() throws Exception {
79
 			verifyZeroInteractions(uut);
79
 			verifyZeroInteractions(uut);
80
 			controller.getView();
80
 			controller.getView();
81
-			verify(uut, times(1)).onCreate(controller);
81
+			verify(uut, times(1)).onCreate();
82
 		}
82
 		}
83
 
83
 
84
 		@Test
84
 		@Test
85
-		public void onStart_CalledBeforeFirstDraw() throws Exception {
85
+		public void onStart_CalledWhenVisible() throws Exception {
86
 			verifyZeroInteractions(uut);
86
 			verifyZeroInteractions(uut);
87
-			controller.getView().getViewTreeObserver().dispatchOnPreDraw();
88
-			controller.getView().getViewTreeObserver().dispatchOnPreDraw();
89
-			verify(uut, times(1)).onStart(controller);
87
+			controller.getView().getViewTreeObserver().dispatchOnGlobalLayout();
88
+			verify(uut, times(1)).onStart();
89
+		}
90
+
91
+		@Test
92
+		public void onStop_CalledWhenInvisible() throws Exception {
93
+			verifyZeroInteractions(uut);
94
+			controller.getView().getViewTreeObserver().dispatchOnGlobalLayout();
95
+			controller.getView().setVisibility(View.GONE);
96
+			controller.getView().getViewTreeObserver().dispatchOnGlobalLayout();
97
+			verify(uut, times(1)).onStop();
98
+		}
99
+
100
+		@Test
101
+		public void onStart_OnStop_Cycle() throws Exception {
102
+			verifyZeroInteractions(uut);
103
+			controller.getView().getViewTreeObserver().dispatchOnGlobalLayout();
104
+			controller.getView().getViewTreeObserver().dispatchOnGlobalLayout();
105
+			verify(uut, times(1)).onStart();
106
+			controller.getView().getViewTreeObserver().dispatchOnGlobalLayout();
107
+			controller.getView().setVisibility(View.INVISIBLE);
108
+			controller.getView().getViewTreeObserver().dispatchOnGlobalLayout();
109
+			controller.getView().getViewTreeObserver().dispatchOnGlobalLayout();
110
+			verify(uut, times(1)).onStop();
111
+			controller.getView().setVisibility(View.VISIBLE);
112
+			controller.getView().getViewTreeObserver().dispatchOnGlobalLayout();
113
+			controller.getView().getViewTreeObserver().dispatchOnGlobalLayout();
114
+			verify(uut, times(1)).onStart();
90
 		}
115
 		}
91
 	}
116
 	}
92
 
117