多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區(qū)平臺 聯(lián)系我們 | 收藏本站
阿里云優(yōu)惠2
您當前位置:首頁 > php開源 > 綜合技術 > React Native之底層源碼分析篇

React Native之底層源碼分析篇

來源:程序員人生   發(fā)布時間:2016-06-06 08:56:41 閱讀次數(shù):3346次

學習React-Native有1段時間了。今天就從源碼的角度來分析下React-Native底層的通訊機制。了解下底層是如何通訊的對開發(fā)也有所好處。

概要

先大概講1下React-Native的通訊進程。RN主要的通訊在于java與js之間,平常我們寫的jsx代碼終究會調用到原生的View。上1篇博客我們也了解到了要新建1個原生模塊需要在java層和js層分別寫1個Module,那這彼此之間聯(lián)系是如何實現(xiàn)的呢?

層次結構

RN總共分為3層,java層,C++層,js層。借用1幅圖來看下:
這里寫圖片描述
Java層:java層就是app原生代碼,它通過啟動C++層的javascript解析器javascriptCore來履行js代碼,從而構建原生UI等。java層依賴于眾多優(yōu)秀開源庫,在圖片處理使用的是Fresco,網(wǎng)絡通訊使用的是okhttp,Json解析工具用jackson,動畫庫用NineOldAndroids等,在java層原生的功能均封裝為Module,如Toast和Log等。
C++層:c++層最主要是封裝了JavaScriptCore,它是1個全新的支持ES6的webKit。Bridge連接了java與js之間的通訊。解析js文件是通過JSCExectutor進行的。
Js層:主要處理事件分發(fā)及UI Layout,平常開發(fā)最經常使用的。通用jsx來寫業(yè)務代碼,通過flexbox來實現(xiàn)布局。不依賴DOM。由于react有 DOM diff這個算法,所以它的效力非常高。

通訊機制

在Java層與Js層的bridge分別存有相同1份模塊配置表,Java與Js相互通訊時,通過將里配置表中的moduleID,methodID轉換成json數(shù)據(jù)的情勢傳遞給到C++層,C++層傳送到js層,通過js層的的模塊配置表找到對應的方法進行履行,如果有callback,則回傳給java層。這里只是大概介紹,后面會有詳細講授。

主要流程與主要類

先看下java層的流程圖:
這里寫圖片描述

  • ReactInstanceManager:主要是用來創(chuàng)建及管理CatalyInstance的實例的上層接口,控制開發(fā)調試,生命周期與ReactRootView所在activity保持1致。
  • ReactRootView:為啟動入口核心類,負責監(jiān)聽及分發(fā)事件并重新渲染元素,App啟動后,其將作為App的root view。
  • CatalystInstance:提供Java與Js互通的環(huán)境,創(chuàng)建Java模塊注冊表及Javascript模塊注冊表,并遍歷實例化模塊,最后通過ReactBridge將Js Bundle傳送到Js引擎。
  • JSBuilderLoader:緩存了JsBundle的信息,封裝了上層加載JsBundle相干接口,CatalystInstance通過其間接調用ReactBridge去加載文件。
  • NativeModuleRegistry:Java層模塊注冊表,即暴露給Js的API集合。
  • JavascriptModuleRegistry:Js層模塊注冊表,負責將所有JavaScriptModule注冊到CatalystInstance。
  • CoreModulePackage:CoreModulesPackage里面定義了RN框架核心的1些Java和JS的module,創(chuàng)建NativeModules&JsModules組件模塊。

源碼分析

加載Module

首先看MainActivity的

protected List<ReactPackage> getPackages() { return Arrays.<ReactPackage>asList( new MainReactPackage(), new AppReactPackage() ); }

AppReactPackage是我們自定義的1個ReactPackage,也就是說如果自己定義了新組件,要在這里添加??聪翿eactActivity,看它的onCreate方法:

protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if(this.getUseDeveloperSupport() && VERSION.SDK_INT >= 23 && !Settings.canDrawOverlays(this)) { Intent mReactRootView = new Intent("android.settings.action.MANAGE_OVERLAY_PERMISSION"); this.startActivity(mReactRootView); FLog.w("React", "Overlay permissions needs to be granted in order for react native apps to run in dev mode"); Toast.makeText(this, "Overlay permissions needs to be granted in order for react native apps to run in dev mode", 1).show(); } this.mReactInstanceManager = this.createReactInstanceManager(); ReactRootView mReactRootView1 = this.createRootView(); mReactRootView1.startReactApplication(this.mReactInstanceManager, this.getMainComponentName(), this.getLaunchOptions()); this.setContentView(mReactRootView1); }

主要完成3個功能,通過createReactInstanceManager創(chuàng)建ReactInstanceManager,它主要是用來創(chuàng)建及管理CatalyInstance的實例的上層接口。第2步是通過createRootView來創(chuàng)建ReactRootView。最后調用ReactRootView的startReactApplication來啟動利用,并把它當作rootview setContentView到界面上。重點看startReactApplication方法:

public void startReactApplication(ReactInstanceManager reactInstanceManager, String moduleName, @Nullable Bundle launchOptions) { UiThreadUtil.assertOnUiThread(); Assertions.assertCondition(this.mReactInstanceManager == null, "This root view has already been attached to a catalyst instance manager"); this.mReactInstanceManager = reactInstanceManager; this.mJSModuleName = moduleName; this.mLaunchOptions = launchOptions; if(!this.mReactInstanceManager.hasStartedCreatingInitialContext()) { this.mReactInstanceManager.createReactContextInBackground(); } if(this.mWasMeasured && this.mIsAttachedToWindow) { this.mReactInstanceManager.attachMeasuredRootView(this); this.mIsAttachedToInstance = true; this.getViewTreeObserver().addOnGlobalLayoutListener(this.getKeyboardListener()); } else { this.mAttachScheduled = true; } }

mJSModuleName是與前端約定好所要啟動的JS Application Name。先看createReactContextInBackground方法,它位于ReactInstanceManager的實現(xiàn)類ReactInstanceManagerImpl中:

public void recreateReactContextInBackground() { Assertions.assertCondition(this .mHasStartedCreatingInitialContext , "recreateReactContextInBackground should only be called after the initial createReactContextInBackground call.") ; this. recreateReactContextInBackgroundInner() ; }

createReactContextInBackground終究調用到recreateReactContextInBackgroundInner:

private void recreateReactContextInBackgroundInner() { UiThreadUtil.assertOnUiThread(); if( this.mUseDeveloperSupport && this.mJSMainModuleName != null) { if (this.mDevSupportManager.hasUpToDateJSBundleInCache()) { this .onJSBundleLoadedFromServer() ; } else if(this .mJSBundleFile == null) { this .mDevSupportManager.handleReloadJS() ; } else { this .mDevSupportManager.isPackagerRunning( new PackagerStatusCallback() { public void onPackagerStatusFetched( final boolean packagerIsRunning) { UiThreadUtil.runOnUiThread( new Runnable() { public void run() { if(packagerIsRunning) { ReactInstanceManagerImpl.this .mDevSupportManager.handleReloadJS() ; } else { ReactInstanceManagerImpl.this .recreateReactContextInBackgroundFromBundleFile() ; } } }) ; } }); } } else { this .recreateReactContextInBackgroundFromBundleFile() ; } }

接著調用recreateReactContextInBackgroundFromBundleFile:

private void recreateReactContextInBackgroundFromBundleFile() { this.recreateReactContextInBackground(new com.facebook.react.bridge.JSCJavaScriptExecutor.Factory(), JSBundleLoader.createFileLoader(this.mApplicationContext, this.mJSBundleFile)); }

經過1系列的周轉,最后調用到了recreateReactContextInBackground:

private void recreateReactContextInBackground(com.facebook.react.bridge.JavaScriptExecutor.Factory jsExecutorFactory, JSBundleLoader jsBundleLoader) { UiThreadUtil.assertOnUiThread(); ReactInstanceManagerImpl.ReactContextInitParams initParams = new ReactInstanceManagerImpl.ReactContextInitParams(jsExecutorFactory , jsBundleLoader); if( this.mReactContextInitAsyncTask == null) { this .mReactContextInitAsyncTask = new ReactInstanceManagerImpl.ReactContextInitAsyncTask( null); this.mReactContextInitAsyncTask.execute( new ReactInstanceManagerImpl.ReactContextInitParams[]{initParams}) ; } else { this .mPendingReactContextInitParams = initParams ; } }

上面代碼通過ReactContextInitAsyncTask這個AsyncTask來初始化ReactCotext。

private final class ReactContextInitAsyncTask extends AsyncTask<ReactInstanceManagerImpl.ReactContextInitParams, Void, ReactInstanceManagerImpl.Result<ReactApplicationContext>> { private ReactContextInitAsyncTask() { } protected void onPreExecute() { if(ReactInstanceManagerImpl.this.mCurrentReactContext != null) { ReactInstanceManagerImpl.this.tearDownReactContext(ReactInstanceManagerImpl.this.mCurrentReactContext); ReactInstanceManagerImpl.this.mCurrentReactContext = null; } } protected ReactInstanceManagerImpl.Result<ReactApplicationContext> doInBackground(ReactInstanceManagerImpl.ReactContextInitParams... params) { Assertions.assertCondition(params != null && params.length > 0 && params[0] != null); try { JavaScriptExecutor e = params[0].getJsExecutorFactory().create(ReactInstanceManagerImpl.this.mJSCConfig == null?new WritableNativeMap():ReactInstanceManagerImpl.this.mJSCConfig.getConfigMap()); return ReactInstanceManagerImpl.Result.of((Object)ReactInstanceManagerImpl.this.createReactContext(e, params[0].getJsBundleLoader())); } catch (Exception var3) { return ReactInstanceManagerImpl.Result.of(var3); } } protected void onPostExecute(ReactInstanceManagerImpl.Result<ReactApplicationContext> result) { try { ReactInstanceManagerImpl.this.setupReactContext((ReactApplicationContext)result.get()); } catch (Exception var6) { ReactInstanceManagerImpl.this.mDevSupportManager.handleException(var6); } finally { ReactInstanceManagerImpl.this.mReactContextInitAsyncTask = null; } if(ReactInstanceManagerImpl.this.mPendingReactContextInitParams != null) { ReactInstanceManagerImpl.this.recreateReactContextInBackground(ReactInstanceManagerImpl.this.mPendingReactContextInitParams.getJsExecutorFactory(), ReactInstanceManagerImpl.this.mPendingReactContextInitParams.getJsBundleLoader()); ReactInstanceManagerImpl.this.mPendingReactContextInitParams = null; } }

ReactContextInitAsyncTask為創(chuàng)建ReactContext的核心類,隨后,調用createReactContext進1步創(chuàng)建ReactContext。在創(chuàng)建完React Context后會調用setUpReactContext,將ReactRootView做為Root View傳遞給UIManagerModule,調用AppRegistry的runApplication去啟動Js Application等??碿reateReactContext的代碼:

private ReactApplicationContext createReactContext(JavaScriptExecutor jsExecutor , JSBundleLoader jsBundleLoader) { FLog.i("React" , "Creating react context."); ReactMarker.logMarker( "CREATE_REACT_CONTEXT_START" ); this.mSourceUrl = jsBundleLoader.getSourceUrl() ; Builder nativeRegistryBuilder = new Builder(); com.facebook.react.bridge.JavaScriptModulesConfig.Builder jsModulesBuilder = new com.facebook.react.bridge.JavaScriptModulesConfig.Builder() ; ReactApplicationContext reactContext = new ReactApplicationContext( this.mApplicationContext); if( this.mUseDeveloperSupport) { reactContext.setNativeModuleCallExceptionHandler(this.mDevSupportManager) ; } ReactMarker.logMarker("PROCESS_PACKAGES_START" ); Systrace.beginSection( 0L, "createAndProcessCoreModulesPackage" ); try { CoreModulesPackage nativeModuleRegistry = new CoreModulesPackage( this, this.mBackBtnHandler , this.mUIImplementationProvider); this.processPackage(nativeModuleRegistry , reactContext, nativeRegistryBuilder, jsModulesBuilder) ; } finally { Systrace.endSection(0L ); } Iterator nativeModuleRegistry2 = this .mPackages.iterator(); while(nativeModuleRegistry2.hasNext()) { ReactPackage javaScriptModulesConfig = (ReactPackage)nativeModuleRegistry2.next(); Systrace.beginSection( 0L, "createAndProcessCustomReactPackage" ); try { this .processPackage(javaScriptModulesConfig , reactContext, nativeRegistryBuilder, jsModulesBuilder) ; } finally { Systrace.endSection(0L) ; } } ReactMarker.logMarker("PROCESS_PACKAGES_END" ); ReactMarker.logMarker( "BUILD_NATIVE_MODULE_REGISTRY_START" ); Systrace.beginSection( 0L, "buildNativeModuleRegistry" ); NativeModuleRegistry nativeModuleRegistry1 ; try { nativeModuleRegistry1 = nativeRegistryBuilder.build(); } finally { Systrace.endSection(0L ); ReactMarker.logMarker( "BUILD_NATIVE_MODULE_REGISTRY_END" ); } ReactMarker.logMarker("BUILD_JS_MODULE_CONFIG_START" ); Systrace.beginSection( 0L, "buildJSModuleConfig" ); JavaScriptModulesConfig javaScriptModulesConfig1 ; try { javaScriptModulesConfig1 = jsModulesBuilder.build(); } finally { Systrace.endSection(0L ); ReactMarker.logMarker( "BUILD_JS_MODULE_CONFIG_END" ); } Object exceptionHandler = this .mNativeModuleCallExceptionHandler != null?this .mNativeModuleCallExceptionHandler: this.mDevSupportManager; com.facebook.react.bridge.CatalystInstanceImpl.Builder catalystInstanceBuilder = ( new com.facebook.react.bridge.CatalystInstanceImpl.Builder()).setReactQueueConfigurationSpec(ReactQueueConfigurationSpec.createDefault()).setJSExecutor(jsExecutor).setRegistry(nativeModuleRegistry1).setJSModulesConfig(javaScriptModulesConfig1).setJSBundleLoader(jsBundleLoader).setNativeModuleCallExceptionHandler((NativeModuleCallExceptionHandler)exceptionHandler) ; ReactMarker.logMarker( "CREATE_CATALYST_INSTANCE_START" ); Systrace.beginSection( 0L, "createCatalystInstance" ); CatalystInstanceImpl catalystInstance ; try { catalystInstance = catalystInstanceBuilder.build(); } finally { Systrace.endSection(0L ); ReactMarker.logMarker( "CREATE_CATALYST_INSTANCE_END" ); } if (this.mBridgeIdleDebugListener != null) { catalystInstance.addBridgeIdleDebugListener(this.mBridgeIdleDebugListener) ; } reactContext.initializeWithInstance(catalystInstance); ReactMarker.logMarker( "RUN_JS_BUNDLE_START" ); Systrace.beginSection( 0L, "runJSBundle" ); try { catalystInstance.runJSBundle(); } finally { Systrace.endSection(0L ); ReactMarker.logMarker( "RUN_JS_BUNDLE_END" ); } return reactContext; }

代碼很長,我們來分段分析。

第1步

com.facebook.react.bridge.JavaScriptModulesConfig.Builder jsModulesBuilder = new com.facebook.react.bridge.JavaScriptModulesConfig.Builder();

創(chuàng)建JavaScriptModulesConfig。

第2步

ReactApplicationContext reactContext = new ReactApplicationContext(this.mApplicationContext);

創(chuàng)建ReactApplicationContext上下文。

第3步

try { CoreModulesPackage nativeModuleRegistry = new CoreModulesPackage(this, this.mBackBtnHandler, this.mUIImplementationProvider); this.processPackage(nativeModuleRegistry, reactContext, nativeRegistryBuilder, jsModulesBuilder); } finally { Systrace.endSection(0L); } Iterator nativeModuleRegistry2 = this.mPackages.iterator(); while(nativeModuleRegistry2.hasNext()) { ReactPackage javaScriptModulesConfig = (ReactPackage)nativeModuleRegistry2.next(); Systrace.beginSection(0L, "createAndProcessCustomReactPackage"); try { this.processPackage(javaScriptModulesConfig, reactContext, nativeRegistryBuilder, jsModulesBuilder); } finally { Systrace.endSection(0L); } }

創(chuàng)建ReactPackage。ReactPackage主要通過createNativeModules、createJSModules和createViewManagers等API去創(chuàng)建本地模塊,JS模塊及視圖組件等。ReactPackage分為framework的CoreModulesPackage和業(yè)務方可選的基礎MainReactPackage,CoreModulesPackage封裝了大部份通訊,調試核心類,如UIManagerModule,這個負責控制Js層Dom到Native View的核心類;看下processPackage方法:

private void processPackage(ReactPackage reactPackage, ReactApplicationContext reactContext, Builder nativeRegistryBuilder, com.facebook.react.bridge.JavaScriptModulesConfig.Builder jsModulesBuilder) { Iterator i$ = reactPackage.createNativeModules(reactContext).iterator(); while(i$.hasNext()) { NativeModule jsModuleClass = (NativeModule)i$.next(); nativeRegistryBuilder.add(jsModuleClass); } i$ = reactPackage.createJSModules().iterator(); while(i$.hasNext()) { Class jsModuleClass1 = (Class)i$.next(); jsModulesBuilder.add(jsModuleClass1); } }

很簡單,拿到具體的native和JS的module把它們添加到對應的builder中。先是添加CoreModulesPackage中的module再添加我們自定義的module,先看CoreModulesPackage中的createNativeModules方法:

public List<NativeModule> createNativeModules(ReactApplicationContext catalystApplicationContext) { Systrace.beginSection(0L, "createUIManagerModule"); UIManagerModule uiManagerModule; try { List viewManagersList = this.mReactInstanceManager.createAllViewManagers(catalystApplicationContext); uiManagerModule = new UIManagerModule(catalystApplicationContext, viewManagersList, this.mUIImplementationProvider.createUIImplementation(catalystApplicationContext, viewManagersList)); } finally { Systrace.endSection(0L); } return Arrays.asList(new NativeModule[]{new AnimationsDebugModule(catalystApplicationContext, this.mReactInstanceManager.getDevSupportManager().getDevSettings()), new AndroidInfoModule(), new DeviceEventManagerModule(catalystApplicationContext, this.mHardwareBackBtnHandler), new ExceptionsManagerModule(this.mReactInstanceManager.getDevSupportManager()), new Timing(catalystApplicationContext), new SourceCodeModule(this.mReactInstanceManager.getSourceUrl(), this.mReactInstanceManager.getDevSupportManager().getSourceMapUrl()), uiManagerModule, new DebugComponentOwnershipModule(catalystApplicationContext)}); }

就是將UIManagerModule、AnimationsDebugModule等裝到build中。
接著添加我們自定義的組件,以自定義Log為例,需要以下內容嗎:

public class AppReactPackage implements ReactPackage{ @Override public List<NativeModule> createNativeModules(ReactApplicationContext reactApplicationContext) { List<NativeModule> modules=new ArrayList<>(); modules.add(new LogModule(reactApplicationContext)); return modules; } @Override public List<Class<? extends JavaScriptModule>> createJSModules() { return Collections.emptyList(); } @Override public List<ViewManager> createViewManagers(ReactApplicationContext reactApplicationContext) { return Collections.emptyList(); } }

很簡單,裝到自定義的List中。

第4步

CatalystInstanceImpl catalystInstance; try { catalystInstance = catalystInstanceBuilder.build(); } finally { Systrace.endSection(0L); ReactMarker.logMarker("CREATE_CATALYST_INSTANCE_END"); }

創(chuàng)建CatalystInstance。CatalystInstance其實不直接面向開發(fā)者,開發(fā)者通ReactInstanceManger間接操作CatalystInstance。CatalystInstance持有對ReactBridge的援用,主要通過ReactBridge這個JNI類去實現(xiàn)Java層與Js層的通訊,ReactBridge由CatalystInstance的Constructor創(chuàng)建。同時初始化的時候調用了ReactQueueConfigurationSpec.createDefault創(chuàng)建了ReactNative通訊的兩個線程 JsQueueThread&NativeModulesQueueThread;
在這里ReactBridge由CatalystInstance的Constructor創(chuàng)建。看下它的構造函數(shù):

private CatalystInstanceImpl(ReactQueueConfigurationSpec ReactQueueConfigurationSpec, final JavaScriptExecutor jsExecutor, NativeModuleRegistry registry, final JavaScriptModulesConfig jsModulesConfig, JSBundleLoader jsBundleLoader, NativeModuleCallExceptionHandler nativeModuleCallExceptionHandler) { this.mPendingJSCalls = new AtomicInteger(0); this.mJsPendingCallsTitleForTrace = "pending_js_calls_instance" + sNextInstanceIdForTrace.getAndIncrement(); this.mDestroyed = false; this.mJSToJavaCallsTeardownLock = new Object(); this.mJavaToJSCallsTeardownLock = new Object(); this.mInitialized = false; FLog.d("React", "Initializing React Bridge."); this.mReactQueueConfiguration = ReactQueueConfigurationImpl.create(ReactQueueConfigurationSpec, new CatalystInstanceImpl.NativeExceptionHandler(null)); this.mBridgeIdleListeners = new CopyOnWriteArrayList(); this.mJavaRegistry = registry; this.mJSModuleRegistry = new JavaScriptModuleRegistry(this, jsModulesConfig); this.mJSBundleLoader = jsBundleLoader; this.mNativeModuleCallExceptionHandler = nativeModuleCallExceptionHandler; this.mTraceListener = new CatalystInstanceImpl.JSProfilerTraceListener(null); try { this.mBridge = (ReactBridge)this.mReactQueueConfiguration.getJSQueueThread().callOnQueue(new Callable() { public ReactBridge call() throws Exception { Systrace.beginSection(0L, "initializeBridge"); ReactBridge var1; try { var1 = CatalystInstanceImpl.this.initializeBridge(jsExecutor, jsModulesConfig); } finally { Systrace.endSection(0L); } return var1; } }).get(); } catch (Exception var8) { throw new RuntimeException("Failed to initialize bridge", var8); } }

注意到這行代碼:

this.mJSModuleRegistry = new JavaScriptModuleRegistry(this, jsModulesConfig);

這里通過jsModulesConfig(封裝了module)創(chuàng)建了JSModuleRegistry。好了js注冊表終究創(chuàng)建成功了。這里有兩個問題,native注冊表在哪創(chuàng)建呢,還有就是注冊表甚么時候傳給js層呢。先留著這兩個問題。
接下來看下initializeBridge方法:

private ReactBridge initializeBridge (JavaScriptExecutor jsExecutor, JavaScriptModulesConfig jsModulesConfig) { this .mReactQueueConfiguration.getJSQueueThread().assertIsOnThread() ; Assertions.assertCondition( this.mBridge == null, "initializeBridge should be called once" ); Systrace.beginSection( 0L, "ReactBridgeCtor" ); ReactBridge bridge ; try { bridge = new ReactBridge(jsExecutor, new CatalystInstanceImpl.NativeModulesReactCallback( null), this.mReactQueueConfiguration.getNativeModulesQueueThread()) ; this.mMainExecutorToken = bridge.getMainExecutorToken() ; } finally { Systrace.endSection(0L ); } Systrace.beginSection(0L , "setBatchedBridgeConfig"); try { bridge.setGlobalVariable("__fbBatchedBridgeConfig" , this.buildModulesConfigJSONProperty( this.mJavaRegistry, jsModulesConfig)); bridge.setGlobalVariable( "__RCTProfileIsProfiling" , Systrace.isTracing( 0L)?"true" :"false") ; } finally { Systrace.endSection(0L ); } this .mJavaRegistry.notifyReactBridgeInitialized(bridge) ; return bridge ; }

ReactBridge將注冊表信息存入與前端互通的全局變量 __fbBatchedBridgeConfig 中,使得Js層與Java層存在一樣的模塊注冊表。bridge.setGlobalVariable是1個native函數(shù)。讓我們猜1下下它的功能,就是用jsModulesConfig這個參數(shù)在js層中生成模塊注冊表,先看1下參數(shù) buildModulesConfigJSONProperty的代碼:

private String buildModulesConfigJSONProperty(NativeModuleRegistry nativeModuleRegistry, JavaScriptModulesConfig jsModulesConfig) { StringWriter stringWriter = new StringWriter(); JsonWriter writer = new JsonWriter(stringWriter); String ioe; try { writer.beginObject(); writer.name("remoteModuleConfig"); nativeModuleRegistry.writeModuleDescriptions(writer); writer.name("localModulesConfig"); jsModulesConfig.writeModuleDescriptions(writer); writer.endObject(); ioe = stringWriter.toString(); } catch (IOException var14) { throw new RuntimeException("Unable to serialize JavaScript module declaration", var14); } finally { try { writer.close(); } catch (IOException var13) { ; } } return ioe; }

看到JsonWriter就知道是把NativeModuleRegistry 和JavaScriptModulesConfig 轉換成Json字符串,其中remoteModuleConfig指NativeModuleRegistry 信息,localModulesConfig指JavaScriptModulesConfig 信息??聪翵avaScriptModulesConfig 的writeModuleDescriptions方法:

public void writeModuleDescriptions(JsonWriter writer) throws IOException { writer.beginObject(); Iterator i$ = this.mModules.iterator(); while(i$.hasNext()) { JavaScriptModuleRegistration registration = (JavaScriptModuleRegistration)i$.next(); writer.name(registration.getName()).beginObject(); this.appendJSModuleToJSONObject(writer, registration); writer.endObject(); } writer.endObject(); }

看下appendJSModuleToJSONObject方法:

private void appendJSModuleToJSONObject(JsonWriter writer, JavaScriptModuleRegistration registration) throws IOException { writer.name("moduleID").value((long)registration.getModuleId()); writer.name("methods").beginObject(); Iterator i$ = registration.getMethods().iterator(); while(i$.hasNext()) { Method method = (Method)i$.next(); writer.name(method.getName()).beginObject(); writer.name("methodID").value((long)registration.getMethodId(method)); writer.endObject(); } writer.endObject(); if(registration.getModuleInterface().isAnnotationPresent(SupportsWebWorkers.class)) { writer.name("supportsWebWorkers").value(true); } }

從上代碼可知生成的json字符串包括moduleID和methodID信息。NativeModuleRegistry 也同理,我們大概看下它的代碼:

void writeModuleDescriptions(JsonWriter writer) throws IOException { Systrace.beginSection(0L, "CreateJSON"); try { writer.beginObject(); Iterator i$ = this.mModuleTable.iterator(); while(i$.hasNext()) { NativeModuleRegistry.ModuleDefinition moduleDef = (NativeModuleRegistry.ModuleDefinition)i$.next(); writer.name(moduleDef.name).beginObject(); writer.name("moduleID").value((long)moduleDef.id); writer.name("supportsWebWorkers").value(moduleDef.target.supportsWebWorkers()); writer.name("methods").beginObject(); for(int i = 0; i < moduleDef.methods.size(); ++i) { NativeModuleRegistry.MethodRegistration method = (NativeModuleRegistry.MethodRegistration)moduleDef.methods.get(i); writer.name(method.name).beginObject(); writer.name("methodID").value((long)i); writer.name("type").value(method.method.getType()); writer.endObject(); } writer.endObject(); moduleDef.target.writeConstantsField(writer, "constants"); writer.endObject(); } writer.endObject(); } finally { Systrace.endSection(0L); } }

接下來我們要找到setGlobalVariable的Native層代碼,C++層代碼我不太懂,這里參考了下他人的分析進程。大概進程是這樣,首先入口是OnLoad.cpp。在其中找到以下代碼:

void Bridge::setGlobalVariable(const std::string& propName, const std::string& jsonValue) { runOnExecutorQueue(*m_mainExecutorToken, [=] (JSExecutor* executor) { executor->setGlobalVariable(propName, jsonValue); }); }

都是塞進runOnExecutorQueue履行隊列里面等待調用,最后回調到JSExecutor,而JSExecutor的實現(xiàn)類是JSCExecutor,最后來看看它的setGlobalVariable方法。

void JSCExecutor::setGlobalVariable(const std::string& propName, const std::string& jsonValue) { auto globalObject = JSContextGetGlobalObject(m_context); String jsPropertyName(propName.c_str()); String jsValueJSON(jsonValue.c_str()); auto valueToInject = JSValueMakeFromJSONString(m_context, jsValueJSON); JSObjectSetProperty(m_context, globalObject, jsPropertyName, valueToInject, 0, NULL); }

懂個大概吧,參數(shù)propName是從Java層傳遞過來的,相當于java代碼中的__fbBatchedBridgeConfig和__RCTProfileIsProfiling。jsPropertyName方法就是buildModulesConfigJSONProperty封裝好的對象。JSContextGetGlobalObject是WeiKit的方法,接下來會調用到js層的MessageQueue中:

const MessageQueue = require('MessageQueue'); const BatchedBridge = new MessageQueue( __fbBatchedBridgeConfig.remoteModuleConfig, __fbBatchedBridgeConfig.localModulesConfig, );

生成兩個映照表,從上面的代碼我們己經分析過了,remoteModuleConfig是NativeModuleRegisty映照表內容。localModulesConfig則是JavaScriptModule內容。
到這里,js就生成了兩張映照表了,這樣java層和js層就都存在一樣的映照表,相互通訊就是通過它來實現(xiàn)。扯遠了,回到createReactView。

第5步

try { catalystInstance.runJSBundle(); } finally { Systrace.endSection(0L); ReactMarker.logMarker("RUN_JS_BUNDLE_END"); }

調用catalystInstance.runJSBundle加載解析Jsbundle。
回到createReactView方法,看catalystInstance.runJSBundle:

public void runJSBundle() { try { this.mJSBundleHasLoaded = ((Boolean)this.mReactQueueConfiguration.getJSQueueThread().callOnQueue(new Callable() { public Boolean call() throws Exception { Assertions.assertCondition(!CatalystInstanceImpl.this.mJSBundleHasLoaded, "JS bundle was already loaded!"); CatalystInstanceImpl.this.incrementPendingJSCalls(); Systrace.beginSection(0L, "loadJSScript"); try { CatalystInstanceImpl.this.mJSBundleLoader.loadScript(CatalystInstanceImpl.this.mBridge); Systrace.registerListener(CatalystInstanceImpl.this.mTraceListener); } catch (JSExecutionException var5) { CatalystInstanceImpl.this.mNativeModuleCallExceptionHandler.handleException(var5); } finally { Systrace.endSection(0L); } return Boolean.valueOf(true); } }).get()).booleanValue(); } catch (Exception var2) { throw new RuntimeException(var2); } }

調用catalystInstance.runJSBundle加載解析Jsbundle。假設在解析進程中出現(xiàn)Exception,統(tǒng)1交給NativeModuleCallExceptionHandler處理。
在創(chuàng)建完React Context后會履行ReactContextInitAsyncTask的onPostExecute。來看下onPostExecute的代碼:

private void setupReactContext(ReactApplicationContext reactContext) { UiThreadUtil.assertOnUiThread(); Assertions.assertCondition(this.mCurrentReactContext == null); this.mCurrentReactContext = (ReactContext)Assertions.assertNotNull(reactContext); CatalystInstance catalystInstance = (CatalystInstance)Assertions.assertNotNull(reactContext.getCatalystInstance()); catalystInstance.initialize(); this.mDevSupportManager.onNewReactContextCreated(reactContext); this.mMemoryPressureRouter.addMemoryPressureListener(catalystInstance); this.moveReactContextToCurrentLifecycleState(); Iterator listeners = this.mAttachedRootViews.iterator(); while(listeners.hasNext()) { ReactRootView arr$ = (ReactRootView)listeners.next(); this.attachMeasuredRootViewToInstance(arr$, catalystInstance); } ReactInstanceEventListener[] var8 = new ReactInstanceEventListener[this.mReactInstanceEventListeners.size()]; var8 = (ReactInstanceEventListener[])this.mReactInstanceEventListeners.toArray(var8); ReactInstanceEventListener[] var9 = var8; int len$ = var8.length; for(int i$ = 0; i$ < len$; ++i$) { ReactInstanceEventListener listener = var9[i$]; listener.onReactContextInitialized(reactContext); } }

這里主要實現(xiàn)兩個功能,第1,調用catalystInstance.initialize()來創(chuàng)建NativeModuleRegistry,好啦,回答了1個問題了哈。

public void initialize() { UiThreadUtil.assertOnUiThread(); Assertions.assertCondition(!this.mInitialized, "This catalyst instance has already been initialized"); this.mInitialized = true; this.mJavaRegistry.notifyCatalystInstanceInitialized(); }

第2,調用attachMeasuredRootView方法。將ReactRootView做為Root View傳遞給UIManagerModule,爾后Js通過UIManager創(chuàng)建的View都會add到該View上。以下:

public void attachMeasuredRootView(ReactRootView rootView) { UiThreadUtil.assertOnUiThread(); this.mAttachedRootViews.add(rootView) ; if( this.mReactContextInitAsyncTask == null && this.mCurrentReactContext != null) { this .attachMeasuredRootViewToInstance(rootView , this.mCurrentReactContext.getCatalystInstance()) ; } }

再來看下attachMeasuredRootViewToInstance這個方法:

private void attachMeasuredRootViewToInstance(ReactRootView rootView , C
生活不易,碼農辛苦
如果您覺得本網(wǎng)站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 国产亚洲福利 | 精品视频一区二区三区免费 | 国产二区精品 | 日本理论免费高清在线视频 | 成zzzwww日本免费 | 性生交酡 | 欧美video粗暴高清免费 | 国产一区二区三区在线免费观看 | 亚洲欧洲国产综合 | 伊人.com| 日韩乱小说 | 日本在线视频二区 | 亚洲综合在线网 | 国产色91 | 97午夜理伦影院在线观看 | 色综合久久综合欧美综合网 | 亚洲最新黄色网址 | 中文字幕第233页 | 国产毛片毛片精品天天看 | 欧洲区二区三区四区 | 亚洲成人精品 | 亚洲欧美色综合一区二区在线 | 91九色精品国产免费 | 一区二区成人国产精品 | 夜夜躁狠狠躁日日躁2021 | 国产精品久久久久久网站 | 三级中文字幕永久在线视频 | 最近更新中文字幕在线 | 中文字幕一区精品 | 波多野结衣中文字幕2022免费 | 男女同房视频免费爽爽 | 亚洲女人天堂 | 美日韩一区二区 | 伊人黄色| 日本中文字幕视频 | 456在线| 亚洲欧洲无码一区二区三区 | 亚洲另类在线观看 | 新japanesevideo乱熟 | www.亚洲天堂.com | 密桃av |