RN,android原生修改debug模式,程式碼伺服器地址方法及原始碼分析
用過debug的都知道,rn可以設定連結的除錯伺服器,大概張這個樣子:
如果我們想在原生程式碼裡修改呢?該怎麼做?
答案可能會出乎你的想象的簡單,這個連結是使用sharedPreferences儲存的只要使用sharedPreferences修改key為”debug_http_host”的值就可以了~~~
不過我們還是深入瞭解一下原始碼的原理,可以幫助我們更好的理解RN,下面我來為您講述一下:
首先要了解這個類,ReactInstanceManager,ReactInstanceManager非常重要,是RN的主控制器, 構建RN世界的執行環境,傳送事件到JS世界, 驅動整個RN世界運轉。
之後,ReactInstanceManager擁有一個DevSupportManager例項,這個類是debug模式相關功能的控制器,所以連結伺服器當然也歸他管啦~~
ReactInstanceManager初始化的時候會通過DevSupportManagerFactory建立mDevSupportManager例項,程式碼如下:
mDevSupportManager = DevSupportManagerFactory.create(
applicationContext,
mDevInterface,
mJSMainModulePath,
useDeveloperSupport,
redBoxHandler,
devBundleDownloadListener,
minNumShakes);
其中mDevInterface宣告如下:
private final ReactInstanceDevCommandsHandler mDevInterface =
new ReactInstanceDevCommandsHandler() {
@Override
public void onReloadWithJSDebugger(JavaJSExecutor.Factory jsExecutorFactory) {
ReactInstanceManager.this.onReloadWithJSDebugger(jsExecutorFactory);
}
@Override
public void onJSBundleLoadedFromServer() {
ReactInstanceManager.this.onJSBundleLoadedFromServer();
}
@Override
public void toggleElementInspector() {
ReactInstanceManager.this.toggleElementInspector();
}
};
看到onJSBundleLoadedFromServer方法沒有,這就是通過伺服器獲取bundle呼叫的方法,哈哈~
@ThreadConfined(UI)
private void onJSBundleLoadedFromServer() {
Log.d(ReactConstants.TAG,”ReactInstanceManager.onJSBundleLoadedFromServer()”);
recreateReactContextInBackground(
mJavaScriptExecutorFactory,
JSBundleLoader.createCachedBundleFromNetworkLoader(
mDevSupportManager.getSourceUrl(),mDevSupportManager.getDownloadedJSBundleFile()));
}
看最後一行,mDevSupportManager.getSourceUrl(),這裡就是去拿我們儲存的URL了。
DevSupportManager是一個介面類,DevSupportManagerImpl類才是真正的實現,DevSupportManagerImpl的getSourceUrl()如下:
@Override
public String getSourceUrl() {
if (mJSAppBundleName ==null) {
return “”;
}
return mDevServerHelper.getSourceUrl(Assertions.assertNotNull(mJSAppBundleName));
}
再看mDevServerHelper.getSourceUrl:
public String getSourceUrl(String mainModuleName) {
return createBundleURL(
mainModuleName,mSettings.isBundleDeltasEnabled() ? BundleType.DELTA : BundleType.BUNDLE);
}
createBundleURL的實現:
private String createBundleURL(String mainModuleID, BundleType type) {
return createBundleURL(
mainModuleID, type,mSettings.getPackagerConnectionSettings().getDebugServerHost());
}
private String createBundleURL(String mainModuleID, BundleType type, String host) {
return String.format(
Locale.US,
host,
mainModuleID,
type.typeID(),
getDevMode(),
getJSMinifyMode());
}
這裡我們看到createBundleURL的引數host就是我們設定的URL了,是通過mSettings.getPackagerConnectionSettings().getDebugServerHost()方法得到,
而這個方法:
public String getDebugServerHost() {
// Check host setting first. If empty try to detect emulator type and use default
// hostname for those
String hostFromSettings =mPreferences.getString(PREFS_DEBUG_SERVER_HOST_KEY,null);
if (!TextUtils.isEmpty(hostFromSettings)) {
return Assertions.assertNotNull(hostFromSettings);
}
String host = AndroidInfoHelpers.getServerHost();
if (host.equals(AndroidInfoHelpers.DEVICE_LOCALHOST)) {
FLog.w(
TAG,
“You seem to be running on device. Run ‘adb reverse tcp:8081 tcp:8081’ ” +
“to forward the debug server’s port to the device.”);
}
return host;
}
我們看到了, String hostFromSettings =mPreferences.getString(PREFS_DEBUG_SERVER_HOST_KEY,null);,通過PREFS_DEBUG_SERVER_HOST_KEY從找到的,而PREFS_DEBUG_SERVER_HOST_KEY就是我們前文所說的”debug_http_host”啦
謝謝閱覽!