Flutter: 2.0.1 kraken: main @ b5574e6Copy the code

View the source must be with a problem, targeted understanding or will fall into the code of the sea, for the whole warehouse has a general overview of the understanding, first look at the effect. Run the sample code in the warehouse (kraken/example/assets/bundle. Js) can see generated flutter node controls:The source snippet is as follows:

var text1 = document.createTextNode('Hello World! ');
var br = document.createElement('br');
var text2 = document.createTextNode('Hello world! ');
p.style.textAlign = 'center'; . p.appendChild(text1);Copy the code

Naturally, we want to know how the JS generated nodes correspond to the DART control; To run js text the JS engine must be ready, how it is initialized; At what time is the external incoming assets/bundle.js read and passed to the engine for execution:

  1. How do JS generated nodes correspond to dart controls

  2. The timing of the js engine initialization

  3. The time to run the specified js file

An overview of

From the sample application (kraken/example/lib/main dart), entrance are a relatively clear, directly to the kraken object as the main body of Scaffold, receives the parameters of the assets/bundle js as bundlePath value, Tracking it solves problem number three.

Kraken is a stateless Widget, create the child controls for _KrakenRenderObjectWidget, it is also a SingleChildRenderObjectWidget, this control is to draw the control of a single node, The two most important methods :RenderObject createRenderObject(BuildContext Context) creates a draw object; _KrakenRenderObjectElement createElement method () to create controls the corresponding node (Element).

To clarify a concept, the front end often talks about rendering, but rendering here does not refer to the specific rendering operation, usually output a section of HTML text or several VNodes for the browser to parse, there is a long way from rendering. The RenderObject inside the flutter is the real rendering. There are dimensions, content, color values, brushes and other related objects to render (there is also a considerable distance from the rendering on the screen). Therefore, in order to prevent confusion on some nouns, RenderObject is always used instead of rendering.

Another concept is the node Element, the Element in flutter does not differentiate between TextNode and has no explicit appendChild operation and is not an Element as described in HTML/XML text. It is created by the Widget (Element createElement() is the Widget’s abstract method) and corresponds to the Widget.

Another thing to review is how the Flutter framework builds a tree of control nodes. In short, we need the Widget object to create a node (Element). The node does the parent-child relationship building, so that the node tree is created by the various types of widgets and their build methods. This step is done by the Flutter framework. External nodes cannot be held by themselves to establish hierarchical relationships, a process called mount.

So you can understand that the only way to _KrakenRenderObjectElement void the mount (Element parent, dynamic newSlot) async {role.

From the Widget Kraken. Build (BuildContext) to a void _KrakenRenderObjectElement. Mount (Element parent, dynamic newSlot) is asynchronous, There’s obviously a lot of stuff created, step by step.

So according to the above overview of the overall divided into 4 steps:

1 Kraken.build()
  _KrakenRenderObjectWidget()

2 _KrakenRenderObjectWidget.createRenderObject

3 _KrakenRenderObjectWidget.createElement

4 _KrakenRenderObjectElement.mount

Copy the code

Step 1 does almost nothing but generate objects that hold external incoming data

Step 4 code is not much, in fact already know the answer to question 3, not sure if the incoming searched _bundlePath final reference, is actually in KrakenController. LoadBundle this method. Digging deeper into the code, take a look at method calls:

4 _KrakenRenderObjectElement. Mount 4.1 KrakenController. LoadBundle KrakenBundle. The getBundle AssetsBundle () *AssetsBundle. Resolve 4.2_evalBundle controller.evalBundle() KrakenBundle. Eval evaluateScripts _evaluateScripts 'evaluateScripts'Copy the code

Load the resource JS text in step 2 4.1. The resource is parsed by AssetsBundle and the base class is KrakenBundle

_evalBundle = _evalBundle = _evalBundle = _evalBundle = _evalBundle = _evalBundle Finally, the JS engine library method ‘evaluateScripts’ was called through THE DART FFI.

So the answer to question 3 is close at hand: Kraken reads the content when the node is mounted and then executes it by the JS engine

The question arises when is the JS engine initialized?