React native Technology Analysis (1)

Source: Internet
Author: User
Preface

React native (RN for short) is not here for its origins, advantages, installation and use. You can Google/Baidu on your own. I sorted out the notes recorded in the previous study of Rn and analyzed some technical ideas in the RN framework based on the RN source code. This is helpful for understanding and better using RN. Due to the limited level, you must correct me if I have some misunderstandings.
Today we will focus on what steps are involved in the RN initialization process and what things are done.

Rn initialization process

Taking IOS as an example, RN rendering is mainly in rctrootview. The initialization code is very simple, that is, creating rootview objects. (due to the deep hierarchy of function calls, it is easy to find out which function is currently in. Please forgive me)

RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation                                                 moduleName:@"LarkRN"                                            initialProperties:nil                                                 launchOptions:launchOptions];

Let's take a look at what the initwithbundleurl function of rctrootview has done:
Create a bridge object in the function and call the initwithbridge function.

- (instancetype)initWithBundleURL:(NSURL *)bundleURL                       moduleName:(NSString *)moduleName                initialProperties:(NSDictionary *)initialProperties                    launchOptions:(NSDictionary *)launchOptions{  RCTBridge *bridge = [[RCTBridge alloc] initWithBundleURL:bundleURL                                            moduleProvider:nil                                             launchOptions:launchOptions];      return [self initWithBridge:bridge moduleName:moduleNameinitialProperties:initialProperties];}

The [self setup] is called again during the bridge object creation process. The setup function calls the createbatchedbridge function to create a batchedbridge object.

- (void)createBatchedBridge{  self.batchedBridge = [[RCTBatchedBridge alloc] initWithParentBridge:self];}

[Self Start] is called again during the initialization of the batchedbridge object. The start function calls the moduleconfig function.

    config = [weakSelf moduleConfig];

The moduleconfig function of the batchedbridge object mainly collects configuration information of all native modules and returns formatted strings.

NSMutableArray<NSArray *> *config = [NSMutableArray new];  for (RCTModuleData *moduleData in _moduleDataByID) {    if (self.executorClass == [RCTJSCExecutor class]) {      [config addObject:@[moduleData.name]];    } else {      [config addObject:RCTNullIfNil(moduleData.config)];    }  }  return RCTJSONStringify(@{    @"remoteModuleConfig": config,  }, NULL);

Configuration information of each native module is managed by the config attribute of the rctmoduledata object. config is an array. The elements in the configuration are module names, constant arrays, and function arrays, export the index array of an asynchronous function (the function type is rctfunctiontypepromise)

NSDictionary<NSString *, id> *constants;NSMutableArray<NSString *> *methods;NSMutableArray<NSNumber *> *asyncMethods;  NSMutableArray *config = [NSMutableArray new];  [config addObject:self.name];  if (constants.count) {    [config addObject:constants];  }  if (methods) {    [config addObject:methods];    if (asyncMethods) {      [config addObject:asyncMethods];    }  }

The start function of the batchedbridge object calls the injectjsonconfiguration function.

  [weakSelf injectJSONConfiguration:config onComplete:nil]

The injectjsonconfiguration function of the batchedbridge object is to add a global variable _ fbbatchedbridgeconfig to JSC.

 [_javaScriptExecutor injectJSONText:configJSON                  asGlobalObjectNamed:@"__fbBatchedBridgeConfig"                             callback:onComplete];

Next, execute the executesourcecode function of the batchedbridge object and execute the RN bundle file (JS Code)

[Self enqueueapplicationscript: sourcecode URL: Self. bundleurl oncomplete: ^ (nserror * loaderror ){... Omitted here}

The executesourcecode function of the batchedbridge object calls the executeapplicationscript function of JSC to run JS Code.

 [_javaScriptExecutor executeApplicationScript:script sourceURL:url onComplete:^(NSError *scriptLoadError) {…}

The executeapplicationscript function of the JSC object puts the downloaded rn bundle file into JSC for execution.

    RCTJSCExecutor *strongSelf = weakSelf;    JSValueRef jsError = NULL;    JSStringRef execJSString = JSStringCreateWithUTF8CString((const char *)script.bytes);    JSValueRef result = JSEvaluateScript(strongSelf->_context.ctx, execJSString, NULL, _bundleURL, 0, &jsError);    JSStringRelease(execJSString);

The batchedbridge object of JS is actually a messagequeue object, which is initialized using the previous _ fbbatchedbridgeconfig variable (native module configuration list ).

    constBatchedBridge=new MessageQueue(        ()=>global.__fbBatchedBridgeConfig    );

Create a remotemodules attribute during the initialization of the messagequeue object

    lazyProperty(this,‘RemoteModules‘,()=>{        Let {remoteModuleConfig}=configProvider();        Let modulesConfig=this._genModulesConfig(remoteModuleConfig);        Let modules=this._genModules(modulesConfig);        this._genLookupTables(            modulesConfig,this._remoteModuleTable,this._remoteMethodTable        );        returnmodules;    });    _genModules(remoteModules){        Let modules={};        remoteModules.forEach((config,moduleID)=>{        Let info=this._genModule(config,moduleID);        if(info){            modules[info.name]=info.module;        }        });        Return modules;    }

The _ genmodules function of the messagequeue object generates model information objects. The key value is the model name. If the module does not export any attributes (constants or functions), only the module ID is recorded; process the exported functions in the model and encapsulate the functions.

    _genModule(config,moduleID):?Object{        Let moduleName,constants,methods,asyncMethods,syncHooks;        if(moduleHasConstants(config)){            [moduleName,constants,methods,asyncMethods,syncHooks]=config;        }else{            [moduleName,methods,asyncMethods,syncHooks]=config;        }        Let module={};        Methods && methods.forEach((methodName,methodID)=>{        Const isAsync = asyncMethods && arrayContains(asyncMethods,methodID);        Const isSyncHook = syncHooks && arrayContains(syncHooks,methodID);        Const methodType=isAsync? MethodTypes.remoteAsync:        isSyncHook ? MethodTypes.syncHook:        MethodTypes.remote;        module[methodName]=this._genMethod(moduleID,methodID,methodType);        });        Object.assign(module,constants);        if(!constants&&!methods&&!asyncMethods){            module.moduleID=moduleID;        }        return{name:moduleName,module};    }

The _ genlookuptables function of the messagequeue object generates a module name retrieval table and a function retrieval table.

    _genLookup(config,moduleID,moduleTable,methodTable){        Let moduleName,methods;        if(moduleHasConstants(config)){            [moduleName,,methods]=config;        }else{            [moduleName,methods]=config;        }        moduleTable[moduleID]=moduleName;        methodTable[moduleID]=Object.assign({},methods);    } 

The messagequeue object registercallablemodule registers the callable module of the JS end and records the names of each module and the list of available functions for the native end to call.

    BatchedBridge.registerCallableModule(‘Systrace‘,Systrace);    registerCallableModule(name,methods){        this._callableModules[name]=methods;    }

After the messagequeue object is initialized, It will be placed in a global variable "_ fbbatchedbridge" for later use.

    Object.defineProperty(global,‘__fbBatchedBridge‘,{value:BatchedBridge});

At this point, the RN initialization process is complete. Simply put, it is to collect the configuration information of the native and JS modules, generate a search table for each module and its available functions, and store it in the global variables in JSC.

React native Technology Analysis (1)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.