Flutter’s hot Reload feature helps you quickly and easily test, build the user interface, add features, and fix bugs without having to restart your application. Hot reload is achieved by injecting the updated source file into the running Dart Virtual Machine (VM). After virtual machines update classes with new fields and functions, the Flutter framework automatically rebuilds the widget tree to quickly see the effect of the changes.

The working principle of

Differences between JIT and AOT:

JIT (Just In Time) : Refers to just-in-time compilation or runtime compilation. Used In Debug mode, it can dynamically deliver and execute code. The startup speed is fast, but the execution performance is affected by runtime compilation.

AOT (Ahead Of Time) : Ahead Of compilation or run-time compilation. Used in Release mode, AOT can generate stable binary code for a specific platform with good execution performance and high running speed. However, AOT needs to be compiled in advance for each execution, resulting in low development and debugging efficiency.

As you can see, in both compilation modes, AOT is compiled statically and the final product is compiled into machine code that can be directly executed, while JIT is compiled dynamically and dart code is compiled into intermediate code that is interpreted by the DART VM as the program runs.

Steps for thermal overloading:

  • Engineering changes: Thermal overloadServerEach file in the project is scanned for additions, deletions, or changes until it finds Dart code that has changed since the last compilation.
  • Incremental compilation: The hot-reload module converts the changed Dart code into incremental compilationDart KernelFile.
  • Push updates: Hot-reload the Server to pass the incremental Dart Kernel fileRPCProtocol, sent to the one that’s running on the phoneDart VM.
  • Code merge: The Dart VM merges the received incremental Dart Kernel file with the existing Dart Kernel file and then reloads the new Dart Kernel file.
  • Widget incremental rendering: Flutter resets its UI thread, notifies, after confirming that the Dart VM resource has been successfully loadedflutter.frameworkReconstruction of the Widget.

Scenarios where hot overloading is not supported

  • Changes in the main method
  • Changes in the initState method
  • A compilation error occurred in the code
  • Changes to global variables and static properties
  • The status of the Widget is incompatible
  • Enumeration and generic type changes

Hot overload source code analysis

Start process Parsing

First create a flutter project, hotload_demo, find flutter-> Packages -> Flutter_tools, open it through Android Studio, and then open Edit Configurations. Create project hotload_demo and configure Working directory (Program arguments).

  1. Start debugging and run the project inbin->flutter_tools.dartThe breakpoint is set on the main function in the

  1. Enter themainFunction, found parsing the parameters passed in, and then doing some callback processing

  1. Now we see that it’s calledrunner.run(args)methods

  1. After the run method is called, it is calledrun.dartThe inside of therunCommand()methods

  1. In the runCommand() method you’ll find our device, which you can see is the emulator device I’m running oniPhone 12 pro Max

  1. Continued debugging found that the terminal printedRunning Xcode build... , xcode build doneThese are in themac.dartInternally processed

Call up some instructions for Xcode to compile and execute

  1. We can see this in the runCommand () methodThe terminal is registered and startedthe

  1. setupTerminal()The help information is printed in the method. WhatR, r,And so on, and now you see that you’re also listening for terminal input

  1. If you look at the implementation of printHelp, it prints out the help information

  1. It turns out that there are two urls at the bottom of the terminal, and the top one isThe dart vmThe bottom one isDevtoolsDebugging tool, Devtools can be used for performance debugging

Scanning incremental files

  1. Listen for terminal input and process it

Here you can see that the input r corresponds to the processing, hot update of the main execution of the code

  1. The inputrforhot reloadRefresh the displayresidentRunner.restart(fullRestart: false)Continue with the following method in restart

  1. To follow uprestartMethod inside_fullRestartHelperMethods and_reloadSourcesMethod to reload the resource file

  1. Log the load time of hotreLoad, and then update the increment file

  1. To follow up_updateDevFSUpdate the increment file, find the device to perform the update file, and then follow in to find the update method

  1. To obtaincontentAnd then look for the file, and then the terminal goes to the directory, and typestrings app.dill.incremental.dillIf there are changes, you can output the contents of the changed file

  1. This is the file that we found from the path,app.dill.incremental.dillContains the contents of the incremental file

Transfer add files to the Dart VM

  1. Transferring incremental filesDevFSContentTo the virtual machine, yes_httpWriter.writerAsynchronous goRPCThe protocol is written to DartVM for updateawait _httpWriter.write(dirtyEntries);.

So if you look at the _httpWriter there is a property called httpAddress which is the address of the Dart VM

  1. So when is the virtual machine createdrunCreate, and there will be a series of registrations

Hot overload engine tuning

Since I downloaded the Code of the Flutter engine and compiled it into the corresponding iOS project, this can be combined here.

  1. How do I get the iOS project in the Flutter project to use the locally compiled engine that is required in the Flutter projectRunnerGenerated.xcconfigEngine in it
// Path of the compile engine FLUTTER_ENGINE=/Users/zhou/engine_download/ SRC // Corresponding simulator debug version LOCAL_ENGINE= iOS_DEBUg_sim_unoptCopy the code

After the configuration was complete and I started running Project Runner, I added a print to the Click method inside the Flutter engine

When I run another project, I click on the screen console and it says yes, that means it’s mounted successfully

  1. Next joint modulationflutter toolsThat need to be inEdit ConfigurationsinsideProgram argumentsConfiguration parameters
run --local-engine-src-path /Users/zhou/engine_download/src --local-engine=ios_debug_sim_unopt
Copy the code

/Users/zhou/engine_download/ SRC /out/ iOS_debug_sim_unopt Find this method, this is the method we call to update the load increment file

Add a breakpoint in the Xcode project you just ran

br set -n "IsolateGroupReloadContext::Reload"

So you have a closed loop, the engine code, the Flutter code, the Flutter tools, and then you have to change the Flutter code, execute r inside the Flutter Tools, Found that this method is implemented to increase the Xcode breakpoint to IsolateGroupReloadContext rendering, verify the steps of thermal overload before.

conclusion

This step by step debugging down to understand the principle of thermal overload. The hot reload of Flutter is code incremental synchronization based on JIT compilation mode. Because the JIT is dynamically compiled and has the ability to compile the Dart code into generated intermediate code that the Dart VM interprets at run time, incremental synchronization can be achieved by dynamically updating the intermediate code.

On the other hand, hot overloading is not supported because it involves saving and restoring state, involving state compatibility and state initialization scenarios, such as incompatible Widget state before and after changes, changes in global variables and static properties, changes in main methods, changes in initState methods, changes in enumerations and generics, etc.

As you can see, hot overloading improves the efficiency of debugging the UI and is ideal for writing interface styles that require repeated review of changes. However, hot overloading itself has some unsupported boundaries due to its state preservation mechanism.

Reference article:

www.jianshu.com/p/46b43554b…

zhuanlan.zhihu.com/p/89870807