Skip to content

Commit 49f20f4

Browse files
foghinaFacebook Github Bot 8
authored and
Facebook Github Bot 8
committedJun 17, 2016
Add ReactInstanceHolder
Reviewed By: astreet Differential Revision: D3328342 fbshipit-source-id: af4e825d0b7c2d3d4490094a939e97cc527dd242
·
v0.80.00.60.2
1 parent d78602b commit 49f20f4

File tree

6 files changed

+219
-115
lines changed

6 files changed

+219
-115
lines changed
 

‎ReactAndroid/src/main/java/com/facebook/react/ReactActivity.java

Lines changed: 40 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -40,38 +40,8 @@ public abstract class ReactActivity extends Activity
4040
private @Nullable PermissionListener mPermissionListener;
4141
private @Nullable ReactInstanceManager mReactInstanceManager;
4242
private @Nullable ReactRootView mReactRootView;
43-
private LifecycleState mLifecycleState = LifecycleState.BEFORE_RESUME;
4443
private DoubleTapReloadRecognizer mDoubleTapReloadRecognizer;
45-
46-
/**
47-
* Returns the name of the bundle in assets. If this is null, and no file path is specified for
48-
* the bundle, the app will only work with {@code getUseDeveloperSupport} enabled and will
49-
* always try to load the JS bundle from the packager server.
50-
* e.g. "index.android.bundle"
51-
*/
52-
protected @Nullable String getBundleAssetName() {
53-
return "index.android.bundle";
54-
};
55-
56-
/**
57-
* Returns a custom path of the bundle file. This is used in cases the bundle should be loaded
58-
* from a custom path. By default it is loaded from Android assets, from a path specified
59-
* by {@link getBundleAssetName}.
60-
* e.g. "file://sdcard/myapp_cache/index.android.bundle"
61-
*/
62-
protected @Nullable String getJSBundleFile() {
63-
return null;
64-
}
65-
66-
/**
67-
* Returns the name of the main module. Determines the URL used to fetch the JS bundle
68-
* from the packager server. It is only used when dev support is enabled.
69-
* This is the first file to be executed once the {@link ReactInstanceManager} is created.
70-
* e.g. "index.android"
71-
*/
72-
protected String getJSMainModuleName() {
73-
return "index.android";
74-
}
44+
private boolean mDoRefresh = false;
7545

7646
/**
7747
* Returns the launchOptions which will be passed to the {@link ReactInstanceManager}
@@ -92,48 +62,31 @@ protected String getJSMainModuleName() {
9262
protected abstract String getMainComponentName();
9363

9464
/**
95-
* Returns whether dev mode should be enabled. This enables e.g. the dev menu.
96-
*/
97-
protected abstract boolean getUseDeveloperSupport();
98-
99-
/**
100-
* Returns a list of {@link ReactPackage} used by the app.
101-
* You'll most likely want to return at least the {@code MainReactPackage}.
102-
* If your app uses additional views or modules besides the default ones,
103-
* you'll want to include more packages here.
65+
* A subclass may override this method if it needs to use a custom {@link ReactRootView}.
10466
*/
105-
protected abstract List<ReactPackage> getPackages();
67+
protected ReactRootView createRootView() {
68+
return new ReactRootView(this);
69+
}
10670

10771
/**
108-
* A subclass may override this method if it needs to use a custom instance.
72+
* Get the {@link ReactNativeHost} used by this app. By default, assumes {@link #getApplication()}
73+
* is an instance of {@link ReactApplication} and calls
74+
* {@link ReactApplication#getReactNativeHost()}. Override this method if your application class
75+
* does not implement {@code ReactApplication} or you simply have a different mechanism for
76+
* storing a {@code ReactNativeHost}, e.g. as a static field somewhere.
10977
*/
110-
protected ReactInstanceManager createReactInstanceManager() {
111-
ReactInstanceManager.Builder builder = ReactInstanceManager.builder()
112-
.setApplication(getApplication())
113-
.setJSMainModuleName(getJSMainModuleName())
114-
.setUseDeveloperSupport(getUseDeveloperSupport())
115-
.setInitialLifecycleState(mLifecycleState);
116-
117-
for (ReactPackage reactPackage : getPackages()) {
118-
builder.addPackage(reactPackage);
119-
}
120-
121-
String jsBundleFile = getJSBundleFile();
122-
123-
if (jsBundleFile != null) {
124-
builder.setJSBundleFile(jsBundleFile);
125-
} else {
126-
builder.setBundleAssetName(getBundleAssetName());
127-
}
128-
129-
return builder.build();
78+
protected ReactNativeHost getReactNativeHost() {
79+
return ((ReactApplication) getApplication()).getReactNativeHost();
13080
}
13181

13282
/**
133-
* A subclass may override this method if it needs to use a custom {@link ReactRootView}.
83+
* Get whether developer support should be enabled or not. By default this delegates to
84+
* {@link ReactNativeHost#getUseDeveloperSupport()}. Override this method if your application
85+
* class does not implement {@code ReactApplication} or you simply have a different logic for
86+
* determining this (default just checks {@code BuildConfig}).
13487
*/
135-
protected ReactRootView createRootView() {
136-
return new ReactRootView(this);
88+
protected boolean getUseDeveloperSupport() {
89+
return ((ReactApplication) getApplication()).getReactNativeHost().getUseDeveloperSupport();
13790
}
13891

13992
@Override
@@ -150,9 +103,11 @@ protected void onCreate(Bundle savedInstanceState) {
150103
}
151104
}
152105

153-
mReactInstanceManager = createReactInstanceManager();
154106
mReactRootView = createRootView();
155-
mReactRootView.startReactApplication(mReactInstanceManager, getMainComponentName(), getLaunchOptions());
107+
mReactRootView.startReactApplication(
108+
getReactNativeHost().getReactInstanceManager(),
109+
getMainComponentName(),
110+
getLaunchOptions());
156111
setContentView(mReactRootView);
157112
mDoubleTapReloadRecognizer = new DoubleTapReloadRecognizer();
158113
}
@@ -161,62 +116,57 @@ protected void onCreate(Bundle savedInstanceState) {
161116
protected void onPause() {
162117
super.onPause();
163118

164-
mLifecycleState = LifecycleState.BEFORE_RESUME;
165-
166-
if (mReactInstanceManager != null) {
167-
mReactInstanceManager.onHostPause();
119+
if (getReactNativeHost().hasInstance()) {
120+
getReactNativeHost().getReactInstanceManager().onHostPause();
168121
}
169122
}
170123

171124
@Override
172125
protected void onResume() {
173126
super.onResume();
174127

175-
mLifecycleState = LifecycleState.RESUMED;
176-
177-
if (mReactInstanceManager != null) {
178-
mReactInstanceManager.onHostResume(this, this);
128+
if (getReactNativeHost().hasInstance()) {
129+
getReactNativeHost().getReactInstanceManager().onHostResume(this, this);
179130
}
180131
}
181132

182133
@Override
183134
protected void onDestroy() {
184135
super.onDestroy();
185136

186-
mReactRootView.unmountReactApplication();
187-
mReactRootView = null;
188-
189-
if (mReactInstanceManager != null) {
190-
mReactInstanceManager.destroy();
137+
if (mReactRootView != null) {
138+
mReactRootView.unmountReactApplication();
139+
mReactRootView = null;
191140
}
141+
getReactNativeHost().clear();
192142
}
193143

194144
@Override
195145
public void onActivityResult(int requestCode, int resultCode, Intent data) {
196-
if (mReactInstanceManager != null) {
197-
mReactInstanceManager.onActivityResult(requestCode, resultCode, data);
146+
if (getReactNativeHost().hasInstance()) {
147+
getReactNativeHost().getReactInstanceManager()
148+
.onActivityResult(requestCode, resultCode, data);
198149
}
199150
}
200151

201152
@Override
202153
public boolean onKeyUp(int keyCode, KeyEvent event) {
203-
if (mReactInstanceManager != null &&
204-
mReactInstanceManager.getDevSupportManager().getDevSupportEnabled()) {
154+
if (getReactNativeHost().hasInstance() && getUseDeveloperSupport()) {
205155
if (keyCode == KeyEvent.KEYCODE_MENU) {
206-
mReactInstanceManager.showDevOptionsDialog();
156+
getReactNativeHost().getReactInstanceManager().showDevOptionsDialog();
207157
return true;
208158
}
209159
if (mDoubleTapReloadRecognizer.didDoubleTapR(keyCode, getCurrentFocus())) {
210-
mReactInstanceManager.getDevSupportManager().handleReloadJS();
160+
getReactNativeHost().getReactInstanceManager().getDevSupportManager().handleReloadJS();
211161
}
212162
}
213163
return super.onKeyUp(keyCode, event);
214164
}
215165

216166
@Override
217167
public void onBackPressed() {
218-
if (mReactInstanceManager != null) {
219-
mReactInstanceManager.onBackPressed();
168+
if (getReactNativeHost().hasInstance()) {
169+
getReactNativeHost().getReactInstanceManager().onBackPressed();
220170
} else {
221171
super.onBackPressed();
222172
}
@@ -229,8 +179,8 @@ public void invokeDefaultOnBackPressed() {
229179

230180
@Override
231181
public void onNewIntent(Intent intent) {
232-
if (mReactInstanceManager != null) {
233-
mReactInstanceManager.onNewIntent(intent);
182+
if (getReactNativeHost().hasInstance()) {
183+
getReactNativeHost().getReactInstanceManager().onNewIntent(intent);
234184
} else {
235185
super.onNewIntent(intent);
236186
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/**
2+
* Copyright (c) 2015-present, Facebook, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree. An additional grant
7+
* of patent rights can be found in the PATENTS file in the same directory.
8+
*/
9+
10+
package com.facebook.react;
11+
12+
public interface ReactApplication {
13+
14+
/**
15+
* Get the default {@link ReactNativeHost} for this app.
16+
*/
17+
ReactNativeHost getReactNativeHost();
18+
}
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/**
2+
* Copyright (c) 2015-present, Facebook, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree. An additional grant
7+
* of patent rights can be found in the PATENTS file in the same directory.
8+
*/
9+
10+
package com.facebook.react;
11+
12+
import javax.annotation.Nullable;
13+
14+
import java.util.List;
15+
16+
import android.app.Application;
17+
18+
import com.facebook.infer.annotation.Assertions;
19+
20+
/**
21+
* Simple class that holds an instance of {@link ReactInstanceManager}. This can be used in your
22+
* {@link Application class} (see {@link ReactApplication}), or as a static field.
23+
*/
24+
public abstract class ReactNativeHost {
25+
26+
private final Application mApplication;
27+
private @Nullable ReactInstanceManager mReactInstanceManager;
28+
29+
protected ReactNativeHost(Application application) {
30+
mApplication = application;
31+
}
32+
33+
/**
34+
* Get the current {@link ReactInstanceManager} instance, or create one.
35+
*/
36+
public ReactInstanceManager getReactInstanceManager() {
37+
if (mReactInstanceManager == null) {
38+
mReactInstanceManager = createReactInstanceManager();
39+
}
40+
return mReactInstanceManager;
41+
}
42+
43+
/**
44+
* Get whether this holder contains a {@link ReactInstanceManager} instance, or not. I.e. if
45+
* {@link #getReactInstanceManager()} has been called at least once since this object was created
46+
* or {@link #clear()} was called.
47+
*/
48+
public boolean hasInstance() {
49+
return mReactInstanceManager != null;
50+
}
51+
52+
/**
53+
* Destroy the current instance and release the internal reference to it, allowing it to be GCed.
54+
*/
55+
public void clear() {
56+
if (mReactInstanceManager != null) {
57+
mReactInstanceManager.destroy();
58+
mReactInstanceManager = null;
59+
}
60+
}
61+
62+
protected ReactInstanceManager createReactInstanceManager() {
63+
ReactInstanceManager.Builder builder = ReactInstanceManager.builder()
64+
.setApplication(mApplication)
65+
.setJSMainModuleName(getJSMainModuleName())
66+
.setUseDeveloperSupport(getUseDeveloperSupport())
67+
.setInitialLifecycleState(LifecycleState.BEFORE_CREATE);
68+
69+
for (ReactPackage reactPackage : getPackages()) {
70+
builder.addPackage(reactPackage);
71+
}
72+
73+
String jsBundleFile = getJSBundleFile();
74+
if (jsBundleFile != null) {
75+
builder.setJSBundleFile(jsBundleFile);
76+
} else {
77+
builder.setBundleAssetName(Assertions.assertNotNull(getBundleAssetName()));
78+
}
79+
80+
return builder.build();
81+
}
82+
83+
/**
84+
* Returns the name of the main module. Determines the URL used to fetch the JS bundle
85+
* from the packager server. It is only used when dev support is enabled.
86+
* This is the first file to be executed once the {@link ReactInstanceManager} is created.
87+
* e.g. "index.android"
88+
*/
89+
protected String getJSMainModuleName() {
90+
return "index.android";
91+
}
92+
93+
/**
94+
* Returns a custom path of the bundle file. This is used in cases the bundle should be loaded
95+
* from a custom path. By default it is loaded from Android assets, from a path specified
96+
* by {@link getBundleAssetName}.
97+
* e.g. "file://sdcard/myapp_cache/index.android.bundle"
98+
*/
99+
protected @Nullable String getJSBundleFile() {
100+
return null;
101+
}
102+
103+
/**
104+
* Returns the name of the bundle in assets. If this is null, and no file path is specified for
105+
* the bundle, the app will only work with {@code getUseDeveloperSupport} enabled and will
106+
* always try to load the JS bundle from the packager server.
107+
* e.g. "index.android.bundle"
108+
*/
109+
protected @Nullable String getBundleAssetName() {
110+
return "index.android.bundle";
111+
}
112+
113+
/**
114+
* Returns whether dev mode should be enabled. This enables e.g. the dev menu.
115+
*/
116+
protected abstract boolean getUseDeveloperSupport();
117+
118+
/**
119+
* Returns a list of {@link ReactPackage} used by the app.
120+
* You'll most likely want to return at least the {@code MainReactPackage}.
121+
* If your app uses additional views or modules besides the default ones,
122+
* you'll want to include more packages here.
123+
*/
124+
protected abstract List<ReactPackage> getPackages();
125+
}
Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
11
package <%= package %>;
22

33
import com.facebook.react.ReactActivity;
4-
import com.facebook.react.ReactPackage;
5-
import com.facebook.react.shell.MainReactPackage;
6-
7-
import java.util.Arrays;
8-
import java.util.List;
94

105
public class MainActivity extends ReactActivity {
116

@@ -17,24 +12,4 @@ public class MainActivity extends ReactActivity {
1712
protected String getMainComponentName() {
1813
return "<%= name %>";
1914
}
20-
21-
/**
22-
* Returns whether dev mode should be enabled.
23-
* This enables e.g. the dev menu.
24-
*/
25-
@Override
26-
protected boolean getUseDeveloperSupport() {
27-
return BuildConfig.DEBUG;
28-
}
29-
30-
/**
31-
* A list of packages used by the app. If the app uses additional views
32-
* or modules besides the default ones, add more packages here.
33-
*/
34-
@Override
35-
protected List<ReactPackage> getPackages() {
36-
return Arrays.<ReactPackage>asList(
37-
new MainReactPackage()
38-
);
39-
}
4015
}

0 commit comments

Comments
 (0)