Only try to load from the packager when it's running

Reviewed By: mkonicek

Differential Revision: D2595489

fb-gh-sync-id: 1d0991fa5414ba4c12476b7ae6c50252e002467b
This commit is contained in:
Andy Street 2015-10-29 07:24:26 -07:00 committed by facebook-github-bot-6
parent e9c7ebfd9a
commit 88655001e3
3 changed files with 91 additions and 3 deletions

View File

@ -41,6 +41,7 @@ import com.facebook.react.bridge.WritableNativeMap;
import com.facebook.react.bridge.queue.CatalystQueueConfigurationSpec;
import com.facebook.react.common.ReactConstants;
import com.facebook.react.common.annotations.VisibleForTesting;
import com.facebook.react.devsupport.DevServerHelper;
import com.facebook.react.devsupport.DevSupportManager;
import com.facebook.react.devsupport.ReactInstanceDevCommandsHandler;
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
@ -232,18 +233,42 @@ public class ReactInstanceManager {
* Trigger react context initialization asynchronously in a background async task. This enables
* applications to pre-load the application JS, and execute global code before
* {@link ReactRootView} is available and measured.
*
* Called from UI thread.
*/
public void createReactContextInBackground() {
if (mUseDeveloperSupport && mJSMainModuleName != null) {
if (mDevSupportManager.hasUpToDateJSBundleInCache()) {
// If there is a up-to-date bundle downloaded from server, always use that
onJSBundleLoadedFromServer();
} else {
} else if (mJSBundleFile == null) {
mDevSupportManager.handleReloadJS();
} else {
mDevSupportManager.isPackagerRunning(
new DevServerHelper.PackagerStatusCallback() {
@Override
public void onPackagerStatusFetched(final boolean packagerIsRunning) {
UiThreadUtil.runOnUiThread(
new Runnable() {
@Override
public void run() {
if (packagerIsRunning) {
mDevSupportManager.handleReloadJS();
} else {
recreateReactContextInBackgroundFromBundleFile();
}
}
});
}
});
}
return;
}
recreateReactContextInBackgroundFromBundleFile();
}
private void recreateReactContextInBackgroundFromBundleFile() {
recreateReactContextInBackground(
new JSCJavaScriptExecutor(),
JSBundleLoader.createFileLoader(mApplicationContext, mJSBundleFile));
@ -579,7 +604,7 @@ public class ReactInstanceManager {
* Example: {@code "index.android.js"}
*/
public Builder setBundleAssetName(String bundleAssetName) {
return this.setJSBundleFile("assets://" + bundleAssetName);
return this.setJSBundleFile(bundleAssetName == null ? null : "assets://" + bundleAssetName);
}
/**

View File

@ -20,6 +20,7 @@ import android.content.Context;
import android.os.Build;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;
import com.facebook.common.logging.FLog;
import com.facebook.infer.annotation.Assertions;
@ -32,6 +33,7 @@ import com.squareup.okhttp.ConnectionPool;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
import com.squareup.okhttp.ResponseBody;
import okio.Okio;
import okio.Sink;
@ -44,7 +46,7 @@ import okio.Sink;
* - Android stock emulator with standard non-configurable local loopback alias: 10.0.2.2,
* - Genymotion emulator with default settings: 10.0.3.2
*/
/* package */ class DevServerHelper {
public class DevServerHelper {
public static final String RELOAD_APP_EXTRA_JS_PROXY = "jsproxy";
private static final String RELOAD_APP_ACTION_SUFFIX = ".RELOAD_APP_ACTION";
@ -62,6 +64,9 @@ import okio.Sink;
private static final String ONCHANGE_ENDPOINT_URL_FORMAT =
"http://%s/onchange";
private static final String WEBSOCKET_PROXY_URL_FORMAT = "ws://%s/debugger-proxy";
private static final String PACKAGER_STATUS_URL_FORMAT = "http://%s/status";
private static final String PACKAGER_OK_STATUS = "packager-status:running";
private static final int LONG_POLL_KEEP_ALIVE_DURATION_MS = 2 * 60 * 1000; // 2 mins
private static final int LONG_POLL_FAILURE_DELAY_MS = 5000;
@ -76,6 +81,10 @@ import okio.Sink;
void onServerContentChanged();
}
public interface PackagerStatusCallback {
void onPackagerStatusFetched(boolean packagerIsRunning);
}
private final DevInternalSettings mSettings;
private final OkHttpClient mClient;
private final Handler mRestartOnChangePollingHandler;
@ -199,6 +208,54 @@ import okio.Sink;
});
}
public void isPackagerRunning(final PackagerStatusCallback callback) {
String statusURL = createPacakgerStatusURL(getDebugServerHost());
Request request = new Request.Builder()
.url(statusURL)
.build();
mClient.newCall(request).enqueue(
new Callback() {
@Override
public void onFailure(Request request, IOException e) {
Log.e(ReactConstants.TAG, "IOException requesting status from packager", e);
callback.onPackagerStatusFetched(false);
}
@Override
public void onResponse(Response response) throws IOException {
if (!response.isSuccessful()) {
Log.e(
ReactConstants.TAG,
"Got non-success http code from packager when requesting status: " +
response.code());
callback.onPackagerStatusFetched(false);
return;
}
ResponseBody body = response.body();
if (body == null) {
Log.e(
ReactConstants.TAG,
"Got null body response from packager when requesting status");
callback.onPackagerStatusFetched(false);
return;
}
if (!PACKAGER_OK_STATUS.equals(body.string())) {
Log.e(
ReactConstants.TAG,
"Got unexpected response from packager when requesting status: " + body.string());
callback.onPackagerStatusFetched(false);
return;
}
callback.onPackagerStatusFetched(true);
}
});
}
private String createPacakgerStatusURL(String host) {
return String.format(PACKAGER_STATUS_URL_FORMAT, host);
}
public void stopPollingOnChangeEndpoint() {
mOnChangePollingEnabled = false;
mRestartOnChangePollingHandler.removeCallbacksAndMessages(null);

View File

@ -475,6 +475,8 @@ public class DevSupportManager implements NativeModuleCallExceptionHandler {
}
public void handleReloadJS() {
UiThreadUtil.assertOnUiThread();
// dismiss redbox if exists
if (mRedBoxDialog != null) {
mRedBoxDialog.dismiss();
@ -496,6 +498,10 @@ public class DevSupportManager implements NativeModuleCallExceptionHandler {
}
}
public void isPackagerRunning(DevServerHelper.PackagerStatusCallback callback) {
mDevServerHelper.isPackagerRunning(callback);
}
private void reloadJSInProxyMode(final ProgressDialog progressDialog) {
// When using js proxy, there is no need to fetch JS bundle as proxy executor will do that
// anyway