-2趾盐,前言
最近我們公司突然開(kāi)始涉足react-native開(kāi)發(fā),老實(shí)說(shuō)小腊,我內(nèi)心是拒絕的救鲤。其一,是因?yàn)槟壳拔覍?duì)于原生開(kāi)發(fā)還不夠精通溢豆,不想突然轉(zhuǎn)向蜒简,其二是因?yàn)閞eact-native目前還沒(méi)有1.0的正式版本,仍然處于探索期不穩(wěn)定漩仙。其三搓茬,我特么開(kāi)發(fā)react-native用的是windows啊犹赖,人家facebook的工程師開(kāi)發(fā)這玩兒用的都是mac【砺兀看在工資的份兒上峻村,我開(kāi)始探索react-native。
-1锡凝,解釋說(shuō)明
- 說(shuō)實(shí)話粘昨,一開(kāi)始就上這么難的話題,我也是沒(méi)辦法窜锯。關(guān)于環(huán)境集成张肾,跑demo等等遇到的這些坑,雖然積攢了一點(diǎn)經(jīng)驗(yàn)锚扎,但是很多時(shí)候吞瞪,我是懵逼的,所以總結(jié)這些經(jīng)驗(yàn)而不說(shuō)出問(wèn)題的根源驾孔,不去探究為什么芍秆,這不是我的風(fēng)格。而通信機(jī)制則是一整套嚴(yán)肅的設(shè)計(jì)翠勉,知根知底妖啥,而且隨著對(duì)于原理的深究,以后對(duì)于問(wèn)題的根源就會(huì)更加明了(不過(guò)windows環(huán)境下還是不要立這種flag比較好)对碌。
- 其次荆虱,作為react-native的菜鳥(niǎo),我駕馭這個(gè)問(wèn)題是有一些難度的俭缓,但是克伊,這也正好是另一種優(yōu)勢(shì),那就是华坦,我能以一個(gè)react-native的菜鳥(niǎo)的角度愿吹,去解釋Java與js的通信機(jī)制,應(yīng)該是對(duì)于剛接觸react-native的原生開(kāi)發(fā)的工程師更加友好惜姐。
- 最后犁跪,我在探究這個(gè)問(wèn)題的過(guò)程中,找到了很多很棒的博文歹袁,比如其實(shí)沒(méi)那么復(fù)雜坷衍!探究react-native通信機(jī)制等,對(duì)于這些前輩,我只有獻(xiàn)上自己的膝蓋条舔。 我目前用的RN的最新版本枫耳,而他們的版本應(yīng)該是有點(diǎn)老,因此代碼其實(shí)跟上面的作者分析有出入孟抗。
0迁杨,鋪墊
首先我們要明白以下幾點(diǎn):
- 在react-native中的通信钻心,主要是Java與JavaScript之間的通信,而實(shí)際上铅协,Java與Js之間是根本沒(méi)辦法直接對(duì)話的捷沸,別看他們看起來(lái)好像是親戚,實(shí)際上他們的關(guān)系就相當(dāng)于雷鋒和雷峰塔的關(guān)系
- 那么Java和Js之間想要能聽(tīng)懂對(duì)方的話狐史,有兩個(gè)必備條件:
- 雙方的信息要能夠傳達(dá)到對(duì)方那里去痒给,就是,先不管聽(tīng)不聽(tīng)的懂 骏全,你首先要把話傳過(guò)去
- 信息傳達(dá)前需要經(jīng)過(guò)翻譯苍柏,才能被接受方正確理解。
- 第一個(gè)條件的解決方案是通過(guò)C++來(lái)做這個(gè)傳話筒姜贡,Java通過(guò)JNI來(lái)call到c++層序仙,然后c++層再把信息傳到j(luò)s,反之亦然鲁豪;第二個(gè)條件的解決方案就是通過(guò)在初始化的時(shí)候構(gòu)造兩本“詞典”,約定好以后說(shuō)話只說(shuō)對(duì)方的“詞典”上的單詞律秃。
所以我們的問(wèn)題其實(shí)只有兩點(diǎn):那就是集中精力觀察“詞典”是怎么傳遞到雙方手里的爬橡,以及兩方是怎么傳遞數(shù)據(jù)的。
1棒动,開(kāi)篇
1.1糙申,Java傳遞“詞典”
首先,對(duì)于詞典還是正確解釋一下船惨,它是某種config柜裸,某種配置文件,每次Java層收到j(luò)s層傳來(lái)的的信息粱锐,都會(huì)讀取這個(gè)文件疙挺,然后才能理解Java層的意思。Java層也是一樣怜浅。他們對(duì)應(yīng)RN的代碼的類分別是:NativeModuleRegistry和JavaScriptModuleRegistry
初始化的開(kāi)端源自ReactActivity铐然,這是react-native中的類,它的onCreate()方法中是這么做的:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getUseDeveloperSupport() && Build.VERSION.SDK_INT >= 23) {
// Get permission to show redbox in dev builds.
if (!Settings.canDrawOverlays(this)) {
Intent serviceIntent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
startActivity(serviceIntent);
FLog.w(ReactConstants.TAG, REDBOX_PERMISSION_MESSAGE);
Toast.makeText(this, REDBOX_PERMISSION_MESSAGE, Toast.LENGTH_LONG).show();
}
}
mReactRootView = createRootView();
//這是最重要的一步
mReactRootView.startReactApplication(
getReactNativeHost().getReactInstanceManager(),
getMainComponentName(),
getLaunchOptions());
setContentView(mReactRootView);
mDoubleTapReloadRecognizer = new DoubleTapReloadRecognizer();
}
mRootView是一個(gè)layout,繼承自FrameLayout,一切的js渲染從這個(gè)Layout上開(kāi)始恶座,它的startReactApplication()方法如下:
public void startReactApplication(
ReactInstanceManager reactInstanceManager,
String moduleName,
@Nullable Bundle launchOptions) {
UiThreadUtil.assertOnUiThread();
// TODO(6788889): Use POJO instead of bundle here, apparently we can't just use WritableMap
// here as it may be deallocated in native after passing via JNI bridge, but we want to reuse
// it in the case of re-creating the catalyst instance
Assertions.assertCondition(
mReactInstanceManager == null,
"This root view has already been attached to a catalyst instance manager");
mReactInstanceManager = reactInstanceManager;
mJSModuleName = moduleName;
mLaunchOptions = launchOptions;
//這是關(guān)鍵
if (!mReactInstanceManager.hasStartedCreatingInitialContext()) {
mReactInstanceManager.createReactContextInBackground();
}
// We need to wait for the initial onMeasure, if this view has not yet been measured, we set which
// will make this view startReactApplication itself to instance manager once onMeasure is called.
if (mWasMeasured) {
attachToReactInstanceManager();
}
}
這里有一個(gè)ReactInstanceManager,它的作用就是管理CatalystInstance的實(shí)例搀暑,CatalystInstance是什么?這是一個(gè)上層抽象的調(diào)用接口)跨琳,Java和Js都可以通過(guò)這個(gè)去調(diào)用對(duì)方自点,當(dāng)然,那兩個(gè)類都是抽象的脉让,實(shí)際上都是通過(guò)它們的XXXXImpl類來(lái)實(shí)現(xiàn)具體的功能桂敛。
那么我們接著往下功炮,注意我們的目的:了解初始化時(shí)如何傳遞那兩本“詞典”的,mReactInstanceManager.createReactContextInBackground();這個(gè)方法就直接調(diào)用到了它的實(shí)現(xiàn)類:XReactInstanceManagerImpl中的createReactContextInBackground然后接下來(lái)的流程就是:
createReactContextInBackground()------> recreateReactContextInBackgroundInner(); -------> recreateReactContextInBackgroundFromBundleLoader(); ---------> recreateReactContextInBackground() ;
到了recreateReactContextInBackground()這個(gè)方法大概是這樣的:
private void recreateReactContextInBackground(
JavaScriptExecutor.Factory jsExecutorFactory,
JSBundleLoader jsBundleLoader) {
UiThreadUtil.assertOnUiThread();
//構(gòu)造參數(shù)
ReactContextInitParams initParams =
new ReactContextInitParams(jsExecutorFactory, jsBundleLoader);
if (mReactContextInitAsyncTask == null) {
// No background task to create react context is currently running, create and execute one.
//執(zhí)行了一個(gè)AsyncTask.......
mReactContextInitAsyncTask = new ReactContextInitAsyncTask();
mReactContextInitAsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, initParams);
} else {
// Background task is currently running, queue up most recent init params to recreate context
// once task completes.
mPendingReactContextInitParams = initParams;
}
}
好我們接下來(lái)看這個(gè)線程內(nèi)部的細(xì)節(jié),重點(diǎn)看doInBackground()這個(gè)方法:
@Override
protected Result<ReactApplicationContext> doInBackground(ReactContextInitParams... params) {
// TODO(t11687218): Look over all threading
// Default priority is Process.THREAD_PRIORITY_BACKGROUND which means we'll be put in a cgroup
// that only has access to a small fraction of CPU time. The priority will be reset after
// this task finishes: https://android.googlesource.com/platform/frameworks/base/+/
d630f105e8bc0021541aacb4dc6498a49048ecea/core/java/android/os/AsyncTask.java#256
Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
Assertions.assertCondition(params != null && params.length > 0 && params[0] != null);
try {
JavaScriptExecutor jsExecutor = params[0].getJsExecutorFactory().create();
//createReactContext()這個(gè)方法被執(zhí)行
return Result.of(createReactContext(jsExecutor, params[0].getJsBundleLoader()));
} catch (Exception e) {
// Pass exception to onPostExecute() so it can be handled on the main thread
return Result.of(e);
}
}
接下去看createReactContext(jsExecutor, params[0].getJsBundleLoader())這個(gè)方法:
/**
* @return instance of {@link ReactContext} configured a {@link CatalystInstance} set
*/
private ReactApplicationContext createReactContext(
JavaScriptExecutor jsExecutor,
JSBundleLoader jsBundleLoader) {
FLog.i(ReactConstants.TAG, "Creating react context.");
ReactMarker.logMarker(CREATE_REACT_CONTEXT_START);
mSourceUrl = jsBundleLoader.getSourceUrl();
//你瞧埠啃,之前提到的兩本“詞典”死宣,他們的Builder已經(jīng)露面了。
NativeModuleRegistry.Builder nativeRegistryBuilder = new NativeModuleRegistry.Builder();
JavaScriptModuleRegistry.Builder jsModulesBuilder = new JavaScriptModuleRegistry.Builder();
final ReactApplicationContext reactContext = new ReactApplicationContext(mApplicationContext);
if (mUseDeveloperSupport) {
reactContext.setNativeModuleCallExceptionHandler(mDevSupportManager);
}
ReactMarker.logMarker(PROCESS_PACKAGES_START);
Systrace.beginSection(
TRACE_TAG_REACT_JAVA_BRIDGE,
"createAndProcessCoreModulesPackage");
try {
//CoreModulesPackage里面定義了RN框架核心的一些Java和JS的module
//通過(guò)processPackage()方法寫(xiě)入到兩本“詞典”的Builder中
CoreModulesPackage coreModulesPackage =
new CoreModulesPackage(this, mBackBtnHandler, mUIImplementationProvider);
processPackage(coreModulesPackage, reactContext, nativeRegistryBuilder, jsModulesBuilder);
} finally {
Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
}
// TODO(6818138): Solve use-case of native/js modules overriding
//這里是開(kāi)發(fā)者自己定義或封裝的一些組件或者事件的package
for (ReactPackage reactPackage : mPackages) {
Systrace.beginSection(
TRACE_TAG_REACT_JAVA_BRIDGE,
"createAndProcessCustomReactPackage");
try {
processPackage(reactPackage, reactContext, nativeRegistryBuilder, jsModulesBuilder);
} finally {
Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
}
}
ReactMarker.logMarker(PROCESS_PACKAGES_END);
ReactMarker.logMarker(BUILD_NATIVE_MODULE_REGISTRY_START);
Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "buildNativeModuleRegistry");
NativeModuleRegistry nativeModuleRegistry;
try {
//好了碴开,創(chuàng)建了用于翻譯Java端的“詞典”
nativeModuleRegistry = nativeRegistryBuilder.build();
} finally {
Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
ReactMarker.logMarker(BUILD_NATIVE_MODULE_REGISTRY_END);
}
NativeModuleCallExceptionHandler exceptionHandler = mNativeModuleCallExceptionHandler != null
? mNativeModuleCallExceptionHandler
: mDevSupportManager;
CatalystInstanceImpl.Builder catalystInstanceBuilder = new CatalystInstanceImpl.Builder()
.setReactQueueConfigurationSpec(ReactQueueConfigurationSpec.createDefault())
.setJSExecutor(jsExecutor)
.setRegistry(nativeModuleRegistry)
//創(chuàng)建了用于翻譯JS端的“詞典”
.setJSModuleRegistry(jsModulesBuilder.build())
.setJSBundleLoader(jsBundleLoader)
.setNativeModuleCallExceptionHandler(exceptionHandler);
//到目前為止毅该。兩本“詞典”都已經(jīng)創(chuàng)建完畢,而且全部都在CatalystInstance這個(gè)類的**實(shí)現(xiàn)類的Builder中**潦牛,此時(shí)你可以回憶一下整個(gè)過(guò)程眶掌,理清一下思路。
ReactMarker.logMarker(CREATE_CATALYST_INSTANCE_START);
// CREATE_CATALYST_INSTANCE_END is in JSCExecutor.cpp
Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "createCatalystInstance");
final CatalystInstance catalystInstance;
try {
//這個(gè)Build()很關(guān)鍵巴碗,它用實(shí)現(xiàn)類的Builder創(chuàng)建了一個(gè)CatalystInstance類朴爬。
catalystInstance = catalystInstanceBuilder.build();
} finally {
Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
ReactMarker.logMarker(CREATE_CATALYST_INSTANCE_END);
}
if (mBridgeIdleDebugListener != null) {
catalystInstance.addBridgeIdleDebugListener(mBridgeIdleDebugListener);
}
ReactMarker.logMarker(RUN_JS_BUNDLE_START);
try {
catalystInstance.getReactQueueConfiguration().getJSQueueThread().callOnQueue(
new Callable<Void>() {
@Override
public Void call() throws Exception {
reactContext.initializeWithInstance(catalystInstance);
Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "runJSBundle");
try {
//在這里就運(yùn)行js代碼說(shuō)明至少在這個(gè)方法之前,“詞典”應(yīng)該傳過(guò)去了
//于是我們刻印回去聚焦到catalystInstance = catalystInstanceBuilder.build();這段代碼
catalystInstance.runJSBundle();
} finally {
Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
ReactMarker.logMarker(RUN_JS_BUNDLE_END);
}
return null;
}
}).get();
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (ExecutionException e) {
if (e.getCause() instanceof RuntimeException) {
throw (RuntimeException) e.getCause();
} else {
throw new RuntimeException(e);
}
}
return reactContext;
}
//將package中的關(guān)于Java和js的東西分別添加到兩本“詞典”的builder中
private void processPackage(
ReactPackage reactPackage,
ReactApplicationContext reactContext,
NativeModuleRegistry.Builder nativeRegistryBuilder,
JavaScriptModuleRegistry.Builder jsModulesBuilder) {
for (NativeModule nativeModule : reactPackage.createNativeModules(reactContext)) {
nativeRegistryBuilder.add(nativeModule);
}
for (Class<? extends JavaScriptModule> jsModuleClass : reactPackage.createJSModules()) {
jsModulesBuilder.add(jsModuleClass);
}
}
catalystInstanceBuilder.build()這段代碼具體實(shí)現(xiàn)如下:
public CatalystInstanceImpl build() {
return new CatalystInstanceImpl(
Assertions.assertNotNull(mReactQueueConfigurationSpec),
Assertions.assertNotNull(mJSExecutor),
Assertions.assertNotNull(mRegistry),
Assertions.assertNotNull(mJSModuleRegistry),
Assertions.assertNotNull(mJSBundleLoader),
Assertions.assertNotNull(mNativeModuleCallExceptionHandler));
}
這個(gè)方法的作用就是直接new了一個(gè)CatalystInstanceImpl類橡淆,那么我們接下去看CatalystInstanceImpl類的構(gòu)造方法:
private CatalystInstanceImpl(
final ReactQueueConfigurationSpec ReactQueueConfigurationSpec,
final JavaScriptExecutor jsExecutor,
final NativeModuleRegistry registry,
final JavaScriptModuleRegistry jsModuleRegistry,
final JSBundleLoader jsBundleLoader,
NativeModuleCallExceptionHandler nativeModuleCallExceptionHandler) {
FLog.d(ReactConstants.TAG, "Initializing React Xplat Bridge.");
mHybridData = initHybrid();
mReactQueueConfiguration = ReactQueueConfigurationImpl.create(
ReactQueueConfigurationSpec,
new NativeExceptionHandler());
mBridgeIdleListeners = new CopyOnWriteArrayList<>();
//這個(gè)就是Java層要傳遞給Js層的“詞典”
mJavaRegistry = registry;
mJSModuleRegistry = jsModuleRegistry;
mJSBundleLoader = jsBundleLoader;
mNativeModuleCallExceptionHandler = nativeModuleCallExceptionHandler;
mTraceListener = new JSProfilerTraceListener(this);
//在這個(gè)方法里召噩,就把Java暴露給Js的詞典傳了進(jìn)去
initializeBridge(
new BridgeCallback(this),
jsExecutor,
mReactQueueConfiguration.getJSQueueThread(),
mReactQueueConfiguration.getNativeModulesQueueThread(),
//getModuleRegistryHolder()這個(gè)方法不過(guò)是一種holder,對(duì)“詞典”做了一些封裝。
mJavaRegistry.getModuleRegistryHolder(this));
mMainExecutorToken = getMainExecutorToken();
}
//你瞧逸爵,native方法具滴,直接call到C++層,接下來(lái)师倔,由C++層通過(guò)各種折騰构韵,然后生成某種配置文件,轉(zhuǎn)發(fā)到Js端
private native void initializeBridge(ReactCallback callback,
JavaScriptExecutor jsExecutor,
MessageQueueThread jsQueue,
MessageQueueThread moduleQueue,
ModuleRegistryHolder registryHolder);
好了趋艘,關(guān)于“詞典”是如何傳遞過(guò)去的疲恢,就解釋到這里,雖然C++層可能有更多操作瓷胧,但是目的就是一個(gè)显拳,把Java類轉(zhuǎn)化成一個(gè)JS讀得懂的格式的文件。
那么我們接下來(lái)看看C++是如何做好傳聲筒的
1.2抖单,數(shù)據(jù)傳遞過(guò)程
初始化完成之后萎攒,Java端和Js端都有了“詞典”,就可把自己的意圖翻譯成對(duì)方能聽(tīng)得懂的話了矛绘,這個(gè)時(shí)候交流就會(huì)暢通了耍休。
1.2.1,Java --> Js
這個(gè)問(wèn)題首先Java層應(yīng)該做的是找到那本Js的詞典货矮,所以我們應(yīng)該尋找Java層是在哪里調(diào)用到了JSModuleRegistry這個(gè)類的羊精,
讓我們退回到ReactContextInitAsyncTask的doInBackground方法中,在詞典傳遞完畢之后,這個(gè)方法基本執(zhí)行完畢喧锦,接下來(lái)是
@Override
protected void onPostExecute(Result<ReactApplicationContext> result) {
try {
setupReactContext(result.get());
} catch (Exception e) {
mDevSupportManager.handleException(e);
} finally {
mReactContextInitAsyncTask = null;
}
// Handle enqueued request to re-initialize react context.
if (mPendingReactContextInitParams != null) {
recreateReactContextInBackground(
mPendingReactContextInitParams.getJsExecutorFactory(),
mPendingReactContextInitParams.getJsBundleLoader());
mPendingReactContextInitParams = null;
}
}
setupReactContext(result.get())這個(gè)方法,然后這個(gè)方法又會(huì)調(diào)用attachMeasuredRootViewToInstance()方法:
private void attachMeasuredRootViewToInstance(
ReactRootView rootView,
CatalystInstance catalystInstance) {
Systrace.beginSection(TRACE_TAG_REACT_JAVA_BRIDGE, "attachMeasuredRootViewToInstance");
UiThreadUtil.assertOnUiThread();
// Reset view content as it's going to be populated by the application content from JS
rootView.removeAllViews();
rootView.setId(View.NO_ID);
UIManagerModule uiManagerModule = catalystInstance.getNativeModule(UIManagerModule.class);
int rootTag = uiManagerModule.addMeasuredRootView(rootView);
rootView.setRootViewTag(rootTag);
@Nullable Bundle launchOptions = rootView.getLaunchOptions();
WritableMap initialProps = Arguments.makeNativeMap(launchOptions);
String jsAppModuleName = rootView.getJSModuleName();
WritableNativeMap appParams = new WritableNativeMap();
appParams.putDouble("rootTag", rootTag);
appParams.putMap("initialProps", initialProps);
//在這里读规,Java找到了那本Js的“詞典”,然后runApplication
catalystInstance.getJSModule(AppRegistry.class).runApplication(jsAppModuleName, appParams);
Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE);
}
其實(shí)catalystInstance.getJSModule(AppRegistry.class).runApplication(jsAppModuleName, appParams)這段代碼比較復(fù)雜燃少,首先getJSModule方法具體實(shí)現(xiàn)在catalystInstanceImpl中束亏,然后會(huì)調(diào)用到mJSModuleRegistry.getJavaScriptModule(this, executorToken, jsInterface)中,代碼如下:
public synchronized <T extends JavaScriptModule> T getJavaScriptModule(
CatalystInstance instance,
ExecutorToken executorToken,
Class<T> moduleInterface) {
HashMap<Class<? extends JavaScriptModule>, JavaScriptModule> instancesForContext =
mModuleInstances.get(executorToken);
if (instancesForContext == null) {
instancesForContext = new HashMap<>();
mModuleInstances.put(executorToken, instancesForContext);
}
JavaScriptModule module = instancesForContext.get(moduleInterface);
if (module != null) {
return (T) module;
}
JavaScriptModuleRegistration registration =
Assertions.assertNotNull(
mModuleRegistrations.get(moduleInterface),
"JS module " + moduleInterface.getSimpleName() + " hasn't been registered!");
//關(guān)鍵
JavaScriptModule interfaceProxy = (JavaScriptModule) Proxy.newProxyInstance(
moduleInterface.getClassLoader(),
new Class[]{moduleInterface},
new JavaScriptModuleInvocationHandler(executorToken, instance, registration));
instancesForContext.put(moduleInterface, interfaceProxy);
return (T) interfaceProxy;
}
什么動(dòng)態(tài)代理不用理他阵具,看 new JavaScriptModuleInvocationHandler(executorToken, instance, registration)這個(gè)類:
private static class JavaScriptModuleInvocationHandler implements InvocationHandler {
private final WeakReference<ExecutorToken> mExecutorToken;
private final CatalystInstance mCatalystInstance;
private final JavaScriptModuleRegistration mModuleRegistration;
public JavaScriptModuleInvocationHandler(
ExecutorToken executorToken,
CatalystInstance catalystInstance,
JavaScriptModuleRegistration moduleRegistration) {
mExecutorToken = new WeakReference<>(executorToken);
mCatalystInstance = catalystInstance;
mModuleRegistration = moduleRegistration;
}
//關(guān)鍵
@Override
public @Nullable Object invoke(Object proxy, Method method, @Nullable Object[] args) throws Throwable {
ExecutorToken executorToken = mExecutorToken.get();
if (executorToken == null) {
FLog.w(ReactConstants.TAG, "Dropping JS call, ExecutorToken went away...");
return null;
}
NativeArray jsArgs = args != null ? Arguments.fromJavaArgs(args) : new WritableNativeArray();
mCatalystInstance.callFunction(
executorToken,
mModuleRegistration.getName(),
method.getName(),
jsArgs
);
return null;
}
}
}
invoke方法通過(guò)mCatalystInstance調(diào)用了callFunction()方法碍遍;不用多想,我們直接在實(shí)現(xiàn)類中去找這個(gè)方法:
@Override
public void callFunction(
ExecutorToken executorToken,
final String module,
final String method,
final NativeArray arguments) {
if (mDestroyed) {
FLog.w(ReactConstants.TAG, "Calling JS function after bridge has been destroyed.");
return;
}
if (!mAcceptCalls) {
throw new RuntimeException("Attempt to call JS function before JS bundle is loaded.");
}
callJSFunction(executorToken, module, method, arguments);
}
private native void callJSFunction(ExecutorToken token,String module, String method,NativeArray arguments);
callFunction()方法里面調(diào)用了callJSFunction()這個(gè)本地方法阳液,然后由C++做轉(zhuǎn)發(fā)怕敬,這個(gè)本地方法傳遞的參數(shù)有token,包名,方法名帘皿,和參數(shù),
至此东跪,從Java端調(diào)用到Js端的過(guò)程,到這里可以宣告結(jié)束了鹰溜。
1.2.2虽填,js-->Java
待續(xù)。
2曹动,矯正
- 暫無(wú)
3卤唉,總結(jié)
- 首先這里沒(méi)有分析js端到j(luò)ava端的過(guò)程,是因?yàn)槲夷壳皩?duì)于js還不是十分熟悉仁期,目前還沒(méi)有把我能用自己的話吧這件事說(shuō)清楚,所以先挖坑竭恬,到時(shí)候一定填上跛蛋。
- 從開(kāi)發(fā)的角度來(lái)看整個(gè)react-native兩端通信,其實(shí)我們最終是避不開(kāi)這些框架層的東西的痊硕,架構(gòu)在原生Android的系統(tǒng)之上的js無(wú)論如何都是需要和Java溝通的赊级,雖然react-native封裝了一些事件和組件,但是假如業(yè)務(wù)需要而框架沒(méi)有封裝岔绸,那你就不得不直面這種通信了理逊。
- 還是原生開(kāi)發(fā)好,windows說(shuō)盒揉。