Source code

Discussion and implementation of native dynamics

Now, with the popularity of big front-end, Native applet, RN, and so on, it seems to be dynamic under the banner of original banner, but in the development process, it will be very much like writing the front end, all kinds of margin padding align and so on. Especially the major frames seem to be repeating a word FlexBox, so we talk about the development of the two words in mobile terminal, dynamic and cross platform.

Compilation dynamics

Each line of code is essentially a string. He does not have any ability to run. It can be run because he has compiled a series of logical and semantic strings that a pedestrian can read, and becomes a set of instructions that the machine can read.

  • Input: code string

  • Compile: (briefly introduce not to expand.  Http://awhisper.github.io/2017/02/26/ nonsense: talk about it in vernacular. )

    • Compiler front-end

      • Lexical analysis: language key recognition in strings

      • Syntax analysis: recognition of loops, judgments, jumps, calls, and other code logic.

      • Generate abstract syntax tree AST: convert code strings to machine understandable, traversable, processing syntax tree.

    • Compile backend

      • Generate intermediate code IR: transform the syntax tree into the executable result product, and produce an intermediate product first.

      • Results: the intermediate code is generated according to the difference of the platform, and different operation results are generated.

  • Output: results of platform operation

    • IOS: executable binary Mach-O file (assembler code can be executed after loading into memory).

    • Android: JVM bytecode (in any JVM platform can be executed).

Dynamic compilation results

The final result of compilation is to be loaded into the running environment. IOS is loaded directly into memory, and Android is loaded into the JVM virtual machine. The loading process is supported by "dynamic" loading, and this dynamic development mode is very close to the original.

  • Android: plug-in technology, dexloader loading

  • IOS: dynamic link library technology, dlopen loading

I don't know about Android, but iOS is worth talking about. The whole process of dylib is called dynamic link library. When we do some common components library, we can choose to create a "static link library" or "dynamic link library". The difference is decided whether to start loading at app or not. But sub dynamic refers to dynamic link (loading) instead of dynamic update.

The code in the static library will be compiled into the same executable file with the main program. If multiple programs refer to the same static library, the static library will have multiple copies in the executable files of multiple programs. The essence of dynamic libraries is to share code segments between multiple executable files, and link them to the virtual address of the main program by linking dylib, which is independent of the main program executable, during the link loading.

But since it is a dynamic link, then download the latest dylib files through the network at the time of loading. Next time you load the latest files, you will naturally be able to do dynamic updates. Here's an example of using manual code to link dylib during operation.

 #define Dylib_PATH "/System/Library/PrivateFrameworks/xxxxx/xxxxx/xxxxx" - (void) dynamicLibraryLoad
{
// dlopen to dynamically load dylib
void *kit = dlopen (Dylib_PATH, RTLD_LAZY); how do you want to invoke the code that is loaded dynamically during runtime? OC has run time and reflection 

Class pacteraClass = NSClassFromString (@ "DynamicOpenMenth"); 
if ((pacteraClass) {
NSLog) (@ Unable to get to);; (c) = x (x) =; C code has the same way as dlsym gets the function address after dynamic loading through function symbols, invocation 

NSString *imsi = nil; 
int (*CTSIMSupportCopyMobileSubscriberIdentity) () = dlsym (kit, CTSIMSupportCopyMobileSubscriberIdentity); 
imsi = (Kit) (());

Unfortunately, this seemingly optimal dynamic road is blocked by apple. Dlopen function runs the above code under the debug package, and the dynamic loading is unimpeded. But on the release package, Apple will be added to the signature check logic. All the unsigned dylib/framework will fail dynamically, so the road is blocked on iOS, but on Android, various plug-in schemes continue.

Cross platform results

The Java itself is designed as a language to compile and run everywhere. As long as the corresponding platform has JVM virtual machine running environment, in other words, the difference between the platforms is tied to JVM, but unfortunately iOS platform does not choose JVM, so it does not cross to iOS.

So the rest of the cross platform language is C/C++. Android and iOS both support the compilation products of C and C++. OC and C and C++ are almost seamless support on iOS, while Android needs JNI to bridge and Java interworking. In the early years, the popular game engine cocos2dx is the logic and rendering with C++. The rendering platform of Flutter is written by skia rendering engine written by C++. In fact, there are many well-known libraries or local algorithms on the two platforms of Android and iOS, and the bottom layer is implemented by C+ +. The Flutter is a popular game engine.

In essence, the design of the compiler background is divided into: first, compile the middle code, and then compile the final result from the middle code according to the platform difference. In itself, it is a design designed to add an intermediate layer for the cross platform. However, because many languages are developing in the process, when the author of different languages is developing the language compiler, the IR intermediate code is not a unified set, so the design is very plentiful and the reality is very backbone. The IR intermediate code does not completely solve the cross platform problem.

Web technology is dynamic - "don't write dead."

In the process of development, even pure native development is often accompanied by some development concepts, "don't write dead."

  • Interface copy? Don't write dead. The server sends out.

  • The style of the interface copy? Do not write dead, shadow, bold, italic, underline server.

  • Cell of tableView? Do not write dead, seven or eight kinds of cell templates, what is rendered under the server?

  • Procedural logic? Do not write dead, depending on the type switch returned by the server, see the situation jump.

  • Function module? Do not write dead, see the switch can be shut down as a whole.

In the process of compiling and running, the code string is compiled into executable compilation results and runs on the corresponding platform. In the idea of "don't write dead," the JSON string, such as configuration information, is described, and the result is changed in real time according to configuration during the running of the program through the network.

All these "do not write dead" is actually a kind of information that can be sent through the network under descriptive values. In the form of JSON, we can read the description information from the code logic to change the pre prepared function logic, so as to achieve the functional change. Even some functional pages, such as "bill details", are now almost in the state of high back-end. In the face of different types of transactions, there is no need for front-end iteration, and a strong backend configuration platform can achieve frequent business access requirements.

In principle, if our description configuration language is comprehensive enough, the part that is solidified in the application is sufficient to identify the inherent capability of describing configuration and execution. Taking account of any currently planned needs and being competent for future functional requirements, our description configuration language is virtually a kind of dynamic update. In fact, this description configuration language forms a specialized language in DSL domain, and a descriptive language in your application configuration system.

Layout engine - interface dynamics

There is such a "DSL" design that can perfectly cover all the interface requirements in the interface. There is also a native fixed code "layout engine" that can resolve this perfect "DSL" design, so that a set of program code of the layout engine can be implemented, and different styles of pages will appear according to the "DSL" of input.

The layout engine is not generated by dynamic demands. It is essentially to solve the problem of screen multi size adaptation. In order to use a "universal" description method, the x y w h absolute coordinates of each sub element in the current window can be calculated in real time by the size of the incoming window area, which is the placement algorithm.

There are many similar layout algorithms, but it can be determined that the layout engine in the browser kernel is the most perfect at the moment, and it is constantly being perfected by W3C and browser manufacturers. The input of the layout engine of the browser kernel is HTML, which expresses the interface element level to describe the CSS layout file to express layout constraint information and style information, and supports the absolute layout, the relative layout, box model, elastic box (known FlexBox), grid layout and other layout algorithms are nested each other. (later, we will give a detailed introduction to the placement algorithm).

 Image.png

This layout engine is essentially native (the browser kernel is written in c++). If you do not use WebView directly, there are many native layout SDK with almost the same idea.

  • The Xib layout file in iOS's AutoLayout:iOS is essentially a tree type XML, which contains interface level information and style information, and reads the XML final generation interface through native code initWithNibName:. If you do not use Xib, instead of using code to create constraints, then native VFL is essentially a DSL, and its internal algorithm is to calculate the final rendering coordinates by calculating the equations of the N element, and its algorithm performance is very poor. In many cases, even if the original autolyout is very stuck (after iOS 12 is optimized).

  • Android's XML writing interface: Android's layout is also very similar to the browser kernel. He also supports writing with XML, and also supports several layouts to meet the needs of rich interface rendering.

  • DTCoreText: Based on the upper encapsulation of iOS native CoreText typesetting library, you can identify HTML and render native directly.

  • RN / Weex rendering framework: in fact, HTML/CSS is also building the Native interface through FlexBox flexible box layout algorithm.

  • Texture framework: originally named AsyncDisplayKit and FB, it is also based on FlexBox elastic box layout algorithm. In fact, there are YogaKit, ComponentsKit and so on. In the final analysis, it comes from FB open source FlexBox layout algorithm library "Yoga" (our bird's nest is also derived from yoga's same layout kernel).

So, in essence, the interface writing mode of HTML+CSS web pages and Android Native XML writing interface are essentially different from the original Xib rendering interface of iOS, and sometimes even faster than the original (iOS Autolayout is too slow). Browser and H5 slow are caused by many complex reasons. But in the layout rendering, the Web technology system is indeed very excellent in the description ability and flexibility of UI, and more and more native dynamic solutions are still inseparable from this set of technical systems in rendering.

Interpretation execution logic dynamic

Simply through interface dynamic, so we made a dynamic App, an interface DSL to the clickable interaction elements plus a scheme routing attribute, whenever this element is clicked, it will jump this route, open a new interface, and the new interface is a brand new downloaded DSL, so as to achieve a pure display page Jump "dynamic" App. After careful analysis, this is actually the most primitive browser page in the early days. Each page is downloaded from a URL by html/css, and then the layout page is displayed. The click interaction effect of each element is to jump to a new URL, so it can be considered that such a dynamic interface App is the most pure web page technology, though it is Native.

But this dynamic is far from what we want, and we hope it can be carried out under different interactions and life cycles.

  • Send a network request to get the latest and most complete data.

  • Local data storage read, data persistence

  • Multi logical judgement of data and presentation to users based on logical results.

  • Wait

Pure interface dynamic is impossible to meet this demand. I think of our thinking above, we need an expression that can describe logic, send it to the client in the form of string, and then display different running results through a set of fixed running environment built by the client.

Compare interface dynamics

  • An expression string that describes the interface: a description language DSL (domain specific language).

  • Runtime environment: executing description expressions requires a layout engine written in native code, which contains various layout algorithms.

Logical dynamics will be more complicated.

  • "Expression string that can describe logic": simply DSL is no longer able to meet the needs. We need a code programming language (scripting language).

  • "Runtime environment": can the compilation result of programming language be executed directly under any platform? What we need is a virtual machine written in C, JS/Lua.

The virtual chance of scripting language strictly follows the compiler front end of compiler theory. Even if the code logic of the target programming language is input during the running of the main program, it will pass through the lexical / grammatical analysis first, thus generating the abstract syntax tree AST, which will eventually transform the program into one running instruction, and execute the compiled instruction set in sequence in the running phase of the virtual machine, and finally get the execution result. (recommend a Book: Lua design and Implementation)

The memory control of scripting language is controlled by the virtual machine. The memory of the script language runs in the context of the virtual machine, which is separated from the native memory.

When you were studying at University, did you learn how to build a computer data structure? The teacher asked to make a calculator, enter a string of "1+2*3-4/5", and use stack data structure to parse the string to calculate the result. This process is very much like interpreting execution.

Lexical analysis: use stack or two fork tree, read a character, a character, read the digital stack, read the symbol / bracket, and press into the symbol stack.

Syntax analysis: build an arithmetic tree according to the priority of your + * / operator and the priority of parentheses.

Abstract syntax tree AST: this tree can execute the result of operation.

 Image.png

At present, the most widely used interpretive execution programming language is JavaScript ~

Binding:

Scripting language can run, can only execute logic, for cycle / if choose judgement / function method / execution callback and other language logic, but if you want to command the device to perform some operations, you still need to call all kinds of API on the native platform, such as disk read and write, such as network request, such as graphics rendering. The script language JS how to write all kinds of three party JS libraries is just running in the context of the virtual machine, unable to operate the device. If you want the virtual machine executed by JS code to operate the hardware of the native environment, you have to build a bridge called Binding (right, actually it is jsbridge, but Binding is more scientific).

  • JS does not have the ability to initiate network requests. The reason why browsers can write Ajax network requests with JS is because their browser writes the network module with c/c++, then gives the module binding to JS, and encapsulates XMLHttpRequest objects and API in JS.

  • JS is unable to change the rendering of the interface, yes! The layout engine and script engine in the browser are 2 separate modules, the layout engine is pure native, and JS is incapable of directly accessing, but the browser specifically gives the layout engine binding to JS, and is encapsulated into Document object and Dom operation API in JS.

  • JS is incapable of storing locally. The reason why browsers can write localstorage with JS is that the browser gives the module binding of the local value storage to JS, and it is encapsulated into localstorage API in JS.

  • Wait

 Image.png

The jsbridge we usually write to WebView is actually an extension of JS's binding concept in the browser, but the ability of binding in the browser is the standard that has been precipitated by W3C Association for more than ten years. It must be universal and extensible. It's not what you want to do, it can give you binding. But we have the advantage of being a client. In our autonomous App, we can use native to expand JS's arbitrary native business capability.

This is the so-called front-end development is limited by browsers, browsers do not support, the front end can not be achieved, but the development of the client itself is developing browsers, the front end wants to do, but can not do, we can make up.

Tips:

Question: if all native capabilities are all binding to JS, and every iOS system Api (possibly tens of thousands) is binding to JS, then can we directly write the full function of native app directly with pure JS? The graphics rendering capability is also binding to JS, does not require html/css plus a complex layout engine, can directly call JS binding good UIView initWithView, addSubview, can write any interface?

Answer: Yes, but it has a price, and every API calling binding is a cross context interface call. This process is very time-consuming. Objects in JS context need serialization, then communicate with the context of native memory through a channel, and then anti serialization in native memory can be processed by native native code (JS and Lua are processed at the C level through data buffer's stack). Therefore, the feasibility of using JS / Lua to write native App directly is still a problem.

  • When JSPatch was not blocked, it took the JSPatch to hotfix bug, and directly used JSPatch to build a new dynamic update function page. This is the principle, but the difference is that JSPatch does not need to binding the tens of thousands of iOS system native Api. Because iOS has runtime, it only needs to use the code to call any native primer, and Android can also reflect. Android can also write and call any Android native hotfix using only the code.

  • C++'s game engine cocos2dx-lua is also the idea. The members of the C2D engine group really give Lua to all C++ API of the entire engine, so in the game circle, a lot of pure Lua games are developed, and only a small amount of C++ development mode is needed when the engine C++ controls do not meet the needs.

Native dynamics and cross platform based on Web Technology

 Image.png The layout engine + script engine constitutes the 2 most important modules of Web technology, and is also the 2 most important core of the browser kernel. All subsequent dynamic programs of non compilation results are all dynamic solutions generated by Web technology.

And these programs are originally cross platform, the bottom layer uses C to realize the kernel, and implements the script engine. As long as the underlying environment is available on all platforms, the upper level DSL and JS can cross platform.

  • WebKit: as shown above, enter HTML / CSS / JS, implemented by browser kernel.

  • ReactNative:

    • The input is JSX, but in fact, HTML CSS JS is mixed together.

    • The layout engine is the open source Yoga Flexbox layout engine of FB written by C.

    • Rendering is directly invoking the native rendering API of each platform through binding mode, and constructs View, Add View.

    • Through the open source JS parsing engine of javascriptCore, as a virtual machine, run and build the JS context.

    • By enriching various native capabilities, native interface components, binding to JS, thus enriching various native capabilities, it can dynamically invoke.

  • Bird's Nest:

    • The input is HTML / CSS / JS, but the JSON tree structure template is analyzed and synthesized on the server side and sent to the client.

    • Client SDK input is JSON tree structure, traversal layout and rendering.

    • The layout engine is the open source Yoga Flexbox layout engine of FB written by C.

    • Rendering is directly invoking the native rendering API of each platform through binding mode, and constructs View, Add View.

    • Through dukTape, the open source embedded JS parsing engine, as a virtual machine, run the JS context.

    • The interface API provides extensions, so that the access side of the nest SDK business side is also very convenient to binding all kinds of native capabilities.

Some native dynamic technology workflow analysis

I believe that the source code of Weex and ReactNative has been analyzed by countless people, and we have seen more or less a lot of different kinds of architecture and design analysis. In fact, many large companies have a set of self developed and more suitable native dynamic technologies. These technologies are free from the open source's maintainability and extensibility and the burden of learning easily. Many internal research technologies, on the premise of properly coupling their own business and back-end services, can have some performance advantages in terms of designing native dynamic capabilities according to the characteristics of the company's business.

To put it simply, it does not seek to design a large and full dynamic framework and rich component ecology. Instead, it is tailored to the needs of its own business, and based on the same principles and ideas, tailor the lightweight lightweight native dynamic framework to suit its business.

Many companies have developed direct HTML + CSS + JS page writing methods, directly changing the technology of Native native dynamic, such as Baidu's self research technology HtmlNative, Didi's teacher Dai Ming also introduced the technology of direct writing HTML code to generate native, and the nest of ants.

This technology enables front-end development to quickly implement dynamically deployed native pages using the traditional HTML + CSS + JS. Its working mechanism is exactly the same as that of the browser kernel. It also integrates HTML & CSS into a tree in the kernel, and puts JS into the virtual machine as a whole, but there are still some differences in the trade-offs between their fine mechanisms.

Server remote processing Dom

  • Dom process variance:

    • Bird's Nest: the process of resolving HTML & CSS does not happen on the client side. It is carried out in the server / development stage IDE. Finally, the interface elements and styles are merged into a JSON tree structure: the JSON format Dom is issued to the client, and the tread tree memory Dom object is sent.

    • WebKit: the process of parsing HTML & CSS occurs on the client side. The network module only downloads the HTML CSS source code. After analyzing and identifying, the Dom tree structure is finally generated: the Dom object in the tree format of memory.

  • JS process differences:

    • Nest: JS code is finally put together in JSON format Dom. When downloaded to the client local, it is taken from Dom to enter the context running environment of virtual machine directly.

    • Webkit: supports the parsing of script tags in HTML, and supports loading JS code directly. The JS source code downloaded from the network module will directly enter the context running environment of the virtual machine.

To put it simply, the bird nest is to build the Dom after downloading the entire Dom tree, while WebKit first downloads all the code resource files, then builds Dom tree locally on the client side, a template ID in the nest, a package, a network link downloading, and auxiliary native cache and update mechanism. In WebKit, whether HTML CSS or JS can be split by file, each file can be downloaded independently by browser, and then cached according to cache-control's information such as Header's cache mechanism.

Client local kernel module

 Image.png

The above is a simple picture of the bird's nest, a total of 2 Bundle, one is the main module of the bird's nest, the other is the 3 C database of the three core of the nest's core.

  • BirdNest

    • View Builder: it is used as the entrance of the entire nest kernel, providing an integrated template processing entry, including template management module of Template Manager, while View Builder is processed by integration, and the output result is Document object.

      • Template Manager: it is the management module of bird nest template, mainly including template download template, download queue control, version update judgment, template reading. The bird nest template provides grayscale capability in the background, unifying the update information sent by the server, and judging the template update process according to the different network environment and the state of the local template.

    • FBDocument: the Dom object of the nest, inheriting from ViewController, the VM - Dom tree generated by the unified management template, the View generated by the Dom tree layout, and the response of each View's UI interactive touch event.

      • The FBView:Dom tree will calculate the frame of each sub View through the layout process, and then create the corresponding native View according to the frame calculated by getView, and then aggregate it into the final Native interface for display. This will create Button Image, Div and so on according to the types of Div, and support horizontal extension.

  • BirdNestBase

    • Layout:FBDocument, when the layout process is in progress, relies mainly on the C++ Flexbox layout algorithm. It looks at the code of Yoga layout.c from RN and Weex, but has been reformed for the two time.

    • Duktap: a lightweight embedded JS interpreter engine, unlike RN and Weex, which use JavascriptCore as the open source JS engine, and the bird nest uses a lighter weight.

    • FbJSON: server generated JSON format Dom structure, that is, template, need JSON analysis, this is the underlying JSON analysis library.

Client local update process

 Image.png

Dom tree local workflow

The main task of View Builder is to build an entire FBDocument, and FBDocument introduced in front of him that he is the core of the entire bird's nest interface, which contains the ViewModel data of the entire interface, that is, Dom tree.

This is the initialization process of FBDocument.

 / / the initialization of a large number of pairs of elephants = {{}}, {{}}, etc., etc., each of them is a node, and each of them is a node, which needs to compute the overall layout and recursively invoke the algorithm of {} / {/ / build up typesetting kernel object = = ();; / / set the layout back to the end of the calculation after the computation is finished; = / / set the external return of the information processing; = / / set the whole processing of the back to the end of the word = =; - (ID) initWithHtml: (NSString*) HTML withData: (NSString*) data andDelegate: (ID) delegate andFallbackDelegate: (delegate), and ()) Start loading template = / / - incoming data JSON form DOM data (HTML parameter) / / / - incoming data JSON morphology data data (data parameter) 
fb_core_load_l (_core, [html UTF8String], [data UTF8String], t, H);

The core of this is the fb_core_load_l method. This method does more things, streamlines the code, then explains the process, and logically marks the key links.

  • Parsing data JSON

  • Parsing HTML JSON for body header

  • Build the JS virtual machine context and execute the JS code in the JS tag of body header data into the virtual machine.

  • Using layout.c's flexbox typesetting algorithm, recursion the entire body's Dom tree, and calculate the frame coordinates of each UI element.

  • Issue load finish event, trigger page rendering construction

 bool fb_core_load_l(fb_core_t* core,
                  const char *page,
                  const char *data,
                  bool js_debuggable,
                  const long flags) {
  
    // ... 省略部分代码
  
// 解析传入的 data json 数据
    if (data != NULL) {
        core->last_data = fbJSON_Parse(data);
    }
  
    // ... 省略部分代码
  
 // 解析传入的 html json 数据
    core->html = fb_parser_json(core, page);
    // ... 省略部分代码
    // html 解析结果里面分拆出 body 与 head
    core->head = fb_node_by_tag(core->html, FB_tag_head);
    core->body = fb_node_by_tag(core->html, FB_tag_body);
    // ... 省略部分代码
    //### 如果head或者body为空,那么就无法正常渲染了,直接返回失败
    if (!core->head || !core->body) {
        return false;
    }
    // ... 省略部分代码
  
    //无 js 的鸟巢业务,即精简模式下不构建 js 虚拟机,非精简模式,构建 js 虚拟机上下文
    if (!core->isLiteMode) {
   A few code words / / non streamlined mode traverses script tag data in data body head, reads JS code, enters duktape virtual machine context 
if ((core->isLiteMode) {
const 
if = (0); ((fb_core_init_script_engine) = {}} ({{}}}} {{}} {} {{}} ({{}}}}}; {} ({}}}}); {} ({}}}}); (()) {} ({}}}); {} ({}}}}); (()) {} ({}}); (()); ((-)); (()); fb_core_init_script_engine (core); If (text) {
fb_script_execute_string (core->scriptEngine, text); omit part of the code / / / to see if the entire node contains JS's onload event; if there is, onload
fb_script_cb_t *onload = fb_node_get_event (core->body, "fb_node_get_event"); (()) (",", ");"}} / / / to see whether the whole node contains a "s" event; if there is, then execute "(") "=" (","); "(") ";" The code layout is used to recursion the whole tree, so that each DOM (that is, the node node object is calculated by layout.c algorithm, frame) 
fb_core_layout (core); omission of part of code X / / send Document Load Finish back, trigger subsequent rendering process 
if (
if);

FlexBox layout algorithm is briefly introduced.

The code process introduced above is fb_core_layout, which is an algorithm for layout calculation. It can take a close look at his source code. His core is to invoke the layoutNode method of the layout Library in layout.c BirdNestBase, and import the root node of core-> body > cssNode tree. After that, the algorithm will recursively complete a tree, and calculate the frame of UI element of each node.

Layout.c code is originally derived from the source code in ReactNative. Subsequent Weex and Juhuasuan's LuaView have used layout.c's pure FlexBox algorithm's open source library, and have made their own optimization and modification. FaceBook is also constantly optimizing, re packaging, and independent open source has become a Yoga library.

No matter which FlexBox algorithm principle is almost the same, interested can understand in detail, the main core is FlexBox to divide the interface into two vertical and horizontal axes, depending on the value of CSS to decide the primary and secondary, and then in the algorithm will follow the primary and secondary axis, the internal elements of elastic fill calculation.

Reference material: Https://halfrost.com/weex_flexbox/

Here I simply go over, do not go deep into the FlexBox algorithm.

Recursive node to determine whether to use caching or re layout

  • Basic parameters for calculating box margins

  • For the main side axis, the available size under the border frame is judged separately.

  • Placing sub views along the main axis traversal subview

    • Whether the child view can be stretched depends on the recursive subview until the subview has the largest or minimum or definite size.

  • Some CSS properties of flex are determined on the spindle to determine the position fine adjustment of the SUBFACES that are flexible.

  • On the side axis, some CSS properties of flex are used to determine the position fine adjustment of the subview.

  • Determine the absolute layout coordinates of the subview frame

The whole algorithm consists of 7 main loops, without detailed analysis of the code. Reference links have been given.

FlexBox elastic box placement algorithm is only part of the WebKit layout capability. It can be said that the layout capability of FlexBox is only a subset of WebKit.

So it can be considered that the layout of the bird's nest (including all RN Weex and all FlexBox framework) is only a subset of WebView's interface layout ability, but if this subset is enough to meet most of the needs, it can also meet business needs.

Creation and rendering of native pages

When the layoutNode layout is finished, it will trigger core->core_load_finish_notify (core) to go back, and then go back to FBDocument to call updateLayout's OC method to render.

The rendering process relies on a core queue _core->actionSeq, which is created by the server when the server builds JSON Dom data. In brief, the content is actually generating a rendering instruction queue according to the level of the Dom tree, for example.

  • Create a root view RootView

  • Create a sub view AView

  • Updating the properties of the subview AView will use the frame result of the layout calculation to update the frame attribute.

  • Add child view AView to RootView

  • Create a sub view BImage

  • Updating the properties of the subview BImage will use the frame result of the layout calculation to update the frame attribute.

  • Add child view BImage to RootView

  • ...

So let's analyze the code workflow of creating and rendering native pages.

 - (void) updateLayout
{
// cyclic instruction queue, execution of each instruction 
for (int i = 0; I < _core->actionSeq->length; ++i) {part / code} / omission of part of the code is invalid, skip 
if (op->node = = NULL) op->node; {} =} / / judgement type of instruction is {} ({}) / {{}}}, and the construction of the word is (= = =)); G / / / omitted part of code View
case / FB_tag_div: {
view = [[FBView alloc] initWithNode:op->node
withDocument:self
withView:nil]; 
break;;}} / / /... Omission part of code X / / original check box View
case FB_tag_checkbox: {
view = [[FBCheckbox; FB_tag_checkbox:;;;}} / / /... Omitted part of code / / native switch View
case FB_tag_switch: {
view = [[FBSwitch alloc] initWithNode:op->node
withDocument:self
withView:nil]; 
break;}} / /... Omission part of the code is / / native text label View
case FB_tag_label: {

NSString *key = FB_tag_label: "" "," (}); "= ="; Ew:nil]; 

[self.dictLabel setObject:view forKey:key];} else {
[view associateNode:op->node]; 
}
break;}} / / / omission part of code X / / / native image View
case FB_tag_img: {

NSString {

NSString = = "" "," (")"; "= ="; "= ="; "(= = =); (= = ="); EtObject:view forKey:key];} else {
[view associateNode:op->node]; 
}

break;}} / / / omission part of code X / / native button View
case FB_tag_button: {
view = [[FBButton alloc] initWithNode:op->node
withDocument:self
withView:nil];;;}} / / / can be extended horizontally all kinds of native... Omitted part of code; }} / / / omitted part of code 
break;}} / View / / to turn a View add to another View to be sub View
case DOM_ADDVIEW: {
FBView *subView = [self findViewByNode:op->node]; 
FBView = =}; and ((+)); (2); WithFormat:@ "%llx", (long long) op->node]; 
[self.dictLabel removeObjectForKey:key];;}} / / / img / cache / img / img / cache / img / cache / img / cache / img / cache / img / cache / img / cache / img / cache / img / cache / img / cache / img / cache / C / C / C / C / C / C / C / C / C / X / C / C / C / C / C / C / C / C / C / C / C / C Ram]; 
NSArray *arrKeyAndValue = [style componentsSeparatedByString:PARAM_DELIMITER_OC]; 
if (arrKeyAndValue.count = = 2) {
NSString *key = [arrKeyAndValue objectAtIndex:0]; *key =}; *arrKeyAndValue;} /} / / part of the attribute, such as font size, such as background color, need to be set up to be set up in the same way; the ratio of the earth to the earth is as high as that of the earth; Attr:key withValue:value]; 
}
break; View} / / part of View can accept interactive events, such as clicking event onClick, which requires the original click event to be tied to the JS of clicked event response / / so this action is used to bind the JS function to native's click event 
case DOM_UPDATE_EVENT: DOM_UPDATE_EVENT: = 2; The JS Native method can be invoked by / / so the action is used to bind the native method to js
case DOM_UPDATE_FUNC: {
FBView *view = [self findViewByNode:op->node]; 

[view updateFunc:[NSString (()); (2); (}} /} / /... Omitting part of code}} / / /... Omitted part of code}

When updateLayout is executed, it calls FBDocument's getView method to get RootView directly, that is, the entire bird's nest interface.

Interaction between native control and JS code

  • DOM_UPDATE_EVENT

  • DOM_UPDATE_FUNC

In fact, it is the 2 core actionSeq instructions introduced above, and these two instructions call the following two methods of FBView respectively.

 - (void) updateEvent: (NSString*) key withValue: (NSString*) value; - (void) updateFunc: (NSString*) key key (());

FBView will have 2 empty methods to implement. Different native View components will rewrite these two methods according to their own components, so as to identify the key and value that are issued correctly.

  • DOM_UPDATE_EVENT

Take FBImage for example, FBImg is a native component that can click and trigger the click event, so in FBImg's updateEvent code, native code recognizes value as "onClick" and knows that it will build a tap gesture recognizer for FBImg. When it hits, it will call onClicked: method, trigger fb_platform_onclick to invoke the onClicked.

 - (void) updateEvent: (NSString *) key withValue: (NSString *) value
{
if ([value = isEqualToString:@ "onclick") {
[self.view;; ((= = =)) ((= = =)) = (= = =)); (2) (= =); (2), "=", ";";

The core of fb_platform_onclick method is to use js's duktap interpreter to invoke fb_script_execute to execute JS code, which is similar to WebView's evaluateScript.

  • DOM_UPDATE_FUNC

Take FBInput for example. FBInput is a control that can be called by focus/unfocus by JS. The native should focus on / focus on 2, and give focus/blur 2 naming to JS.

 - (void) updateFunc: (NSString*) key withValue: (NSString*) value {

if ([key isEqualToString:@ "focus") isEqualToString:@;

In the case of JS calling native actively, the real link native and JS duktape engine are two fb_script.c & fb_script_ductape.c classes. The main work of these two classes is to carry out the serialization of JS's memory data, reverse sequence into native data, to identify the data, and then call the corresponding native method to transfer data.

A little unfolding is:

  • The fb_script_register_doc method in fb_script_duktape binds all the names and characters of the native method table to the JS environment. When any JS code calls these binding names, it triggers the fb_script_doc_func method.

  • The fb_script_doc_func method triggers the fb_script_bind_node method.

  • The fb_script_bind_node method triggers the fb_script_node_func method.

  • The name of the method will be identified in fb_script_node_func. If it is "blur" / "focus", it will trigger fb_core_add_action.

  • The function of fb_core_add_action is to create DOM_UPDATE_FUNC events and put them into execution queue.

This is still more complex, covering the whole JS and OC 2 contextual interaction, if you can recommend reading these two categories of source code.

Comparison of dynamic schemes

Thinking about the trend of Technological Development

Native Bird nest ReactNative Weex WebView applet WebView H5
Rendering ability Any effect can be achieved. Only FlexBox layout supports the effect. Only support the effect of FlexBox algorithm Only support Web standard algorithm effect
Not Canvas capacity temporarily.
Only support Web standard algorithm effect
Not Canvas capacity temporarily.
Layout performance Frame layout best
AutoLayout layout depends on algorithm.
FlexBox performance is well recognized. FlexBox performance is well recognized. Support various layout algorithms used in combination, in layout operation, CSS write worse, worse performance, priority use of FlexBox will also have good performance. Support various layout algorithms used in combination, in layout operation, CSS write worse, worse performance, priority use of FlexBox will also have good performance.
Rendering performance Native rendering can render API directly from the underlying graphics, or render native UI components. Native UI component rendering Native UI component rendering WebView rendering + native component UI patch
Mixed rendering
WebView rendering
The bottom layer directly calls the system GUI API of the platform.
Operational performance Best performance JS virtual machine runs and performs better than native.
There are JS and native context switching overhead.
The performance of JS virtual machine is not as good as native.
The JS running environment has a large React JS framework.
There are JS and native context switching overhead.
The performance of JS virtual machine is not as good as native.
The JS running environment has a large React JS framework.
There are JS and native context switching overhead.
The performance of JS virtual machine is not as good as native.
Is there a huge JS framework that depends on business?
Whether there is JS or native context switching depends on whether or not Hybrid
Update package content Pure data updates can only be refreshed by network interface. HTML CSS JS integrated JSON template update HTML CSS JS image resources packaged into jsbundle package update HTML CSS JS pictures are packaged into small programs, offline packages are updated as a whole. HTML CSS JS images are scattered and independent, updating their respective ones.
Deployment update mechanism Unable to update hot Version update control for the entire package. Version update control for the entire package.
If the package is too large, it can assist in unpacking and subcontracting update strategy.
Version update control for the entire package.
The strategy of overloading, subcontracting and subcontracting is updated.
Each file is updated independently, controlled by WebView cache protocol.
Native version dependency I want to issue a copy every time. Only bird nest components and frames need to be expanded before they need to be expanded (but the RN is not comprehensive enough). Only RN's Native components and frameworks need to be expanded before they need to be expanded. (relatively speaking, Native components are relatively perfect, and the frequency of editions is less than that of bird's Nest). Only RN's Native components and frameworks need to be expanded before they need to be expanded. (relatively speaking, small programs have many Web components, few Native components, and fewer publishing opportunities). No edition at all.
Unless Hybrid WebView container framework is developed iteratively.

Many people will draw this comparison form to show which technical plan is good or bad. But if you look at this form carefully, you will find that in the direction of Web technology dynamic, all the technical solutions are not fragmented, but come down in one continuous line.

  • Native is the starting point of the dynamic road, and its dynamic capability is almost 0.

  • WebView is the end of the dynamic road, and the dynamic capability is perfect (after all, the W3C standard has precipitated for ten or twenty years).

However, because the performance of the mobile terminal is not as good as that of the PC computer, the PC terminal has the most mature Web function and can not be used in the mobile terminal. So in the mobile terminal, according to the performance of mobile terminal devices, along the Web standard development route, we first select the most needed dynamic capabilities to integrate into the mobile terminal.

  • Native is the starting point of the dynamic road, and its dynamic capability is almost 0.

    • > from Native to WebView to expand and expand.

      • Select only the highest performance FlexBox layout capability.

      • Minimalist JS engine framework

      • Offline download after whole package downloading.

    • > forming bird's nest

      • Expand the more perfect Native UI components.

      • An efficient React development framework for JS layer is expanded.

      • Jsbundle's whole packet subcontracting and unpacking update mechanism

      • More reasonable framework design

    • > forming RN

  • WebView is the end of the dynamic road, and the dynamic capability is perfect (after all, the W3C standard has precipitated for ten or twenty years).

    • > from WebView to Native to eliminate unnecessary function overhead.

      • Delete every file fine-grained real-time update control and cache control of WebView, instead of offline package local loading.

      • In CSS, the layout design of FlexBox is recommended as far as possible.

      • In JS, this mandatory framework introduces MVVM framework and DOM diff algorithm to prohibit arbitrary operation of DOM, resulting in performance degradation.

      • Multi WebView sharing service worker unified logic JS context running JS asynchronously

      • On the basis of WebView, integrate native UI components and Hybrid rendering to improve the performance of some special components.

    • > forming the WebView applet.

A consensus is that the current stage of native dynamics is relatively acceptable: that is to follow Web standards. Because Web's technology system is really well designed in terms of UI's description ability and flexibility, and relevant developers are also good at recruiting. So, if hybrid development refers to running a Web standard in Native, it is an eternal trend to see Qi Runtime writing GUI and bridging part of Native capability to call this Runtime.

Quote from: Http://awhisper.github.io/2016/06/16/ front-end 10 years after reading

Author: toss up the monosodium glutamate of fan er

Links: Http://awhisper.github.io/2019/03/03/native-dynamic/

Fabulous ( Zero )

This article is composed of Contributor Creation, article address: Https://blog.isoyu.com/archives/yuanshengdongtaihuatantaoyushixian.html
Use Knowledge sharing signature 4 The international license agreement is licensed. In addition to the reprint / provenance, all originals or translations of this site must be signed before retransmission. The final edit time is April, 23, 2019 at 11:40 PM.

Hot articles

Comment

[required]

Invisibility?

Please wait three seconds after submission, so as not to cause unsuccessful successes and duplication.