Android开发经验谈Android开发Android技术知识

Flutter高级开发——【热重载原理&源码解析】

2023-02-06  本文已影响0人  谁动了我的代码

简介

Flutter 的热重载(hot reload)功用能够帮助您在无需从头启动应用的情况下快速、轻松地进行测验、构建用户界面、添加功用以及修正过错。经过将更新后的源代码文件注入正在运转的Dart虚拟机(VM)中来完成热重载。在虚拟机运用新的的字段和函数更新类后,Flutter 结构会自动从头构建widget树,以便快速检查更改的作用。

为什么需要热重载?【简单描述】

程序猿在刀耕火种的时代,开发调试是这样子的:

image

当项目不大,人数不多的情况下,画面是非常和谐的,效率也是毋庸置疑的高效。但现实是,在大公司,项目往往很大,编译巨慢无比,同时开发人员众多,有着非常严格的流程制度,导致看起来本没有问题的开发调试流程,变得异常的痛苦,降低了个体的效率,这里强调下,指的是个体的效率,个人认为越是完善的流程体系,对个体的约束往往越强,但从团队的角度去看待效率,一定是能 1+ 1 大于 2 的。

而此时的心情是这样子的:

image

而有了热重载,开发调试是这样子的:

image

心情也就成这样子的:

image

热重载原理

Flutter热重载的流程

如下所示:

image

热重载的源码解析

启动流程解析

首要创立一个 flutter 项目 hotload_demo,找到flutter->packages->flutter_tools,经过 Android Studio 翻开,然后翻开Edit Configurations,把方才创立的工程 hotload_demo装备Working directory,Program arguments先装备一个参数 run。

image
  1. 开端调试运转项目,在 bin->flutter_tools.dart 中的main函数打上断点,能够看到参数有传入进来
image
  1. 进入 main 函数,发现在对传进来的参数进行分析,然后进行一些回调处理
image
  1. 下面发现调用了 runner.run(args) 办法
image
  1. run 办法调用完毕后,会调用run.dart里边的 runCommand() 办法
image
  1. 在 runCommand() 办法里边会找到咱们的设备,这里能够看出设备便是我运转的模拟器设备 iPhone 12 pro Max
image
  1. 继续调试发现在终端打印了 Running Xcode build..., xcode build done, 这些是在mac.dart里边处理的
image

调起一些指令给Xcode编译履行

image
  1. 在 runcommand() 办法里边,咱们就能够看到开端注册和启动终端了
image
  1. setupTerminal() 办法里边就会打印那些帮助信息,什么r 、R等等,而且下面看到也开端监听终端的输入了
image
  1. 能够看下 printHelp 办法的完成,便是输出打印了那些帮助信息
image
  1. 发现终端最下面输出了两个 URL ,上面这个是dart虚拟机的,下面这个是 Devtools 调试工具,Devtools 能够进行功能的调试
image image

扫描增量文件

  1. 监听终端的输入,然后进行处理
image image

这里能够看到输入 r 对应的处理,热更新首要履行的代码

image
  1. 输入r 进行 hot reload 刷新展示 residentRunner.restart(fullRestart: false),restart 中继续履行下面的办法
image
  1. 跟进 restart 办法里边的 _fullRestartHelper 办法和 _reloadSources 办法对资源文件进行从头加载
image
  1. 记录 hotreload 的加载时间,然后更新增量文件
image
  1. 跟进 _updateDevFS 更新增量文件,找到设备履行更新文件,再跟进去找到了update办法
image image
  1. 获取 content 中的途径然后查找这个文件,然后终端进入这个目录,输入 strings app.dill.incremental.dill,假如有更改内容就能够输出更改文件的内容
image
  1. 这便是依据途径找到的文件,app.dill.incremental.dill 就包含增量的文件内容
image

传输添加文件给 Dart VM

  1. 传输增量文件 DevFSContent 给虚拟机,经过 _httpWriter.writer 异步走 RPC 协议写入到 DartVM中更新await _httpWriter.write(dirtyEntries);,
image

能够检查这个_httpWriter里边有个特点 httpAddress 便是 Dart VM 的地址

image
  1. 那虚拟机什么时候创立呢,其实打断点能够看到便是开端 run 的时候就创立了,创立里边就会有一系列的注册
image image

热重载引擎的联调

因为之前我是下载了flutter 引擎代码的,然后编译成了对应的iOS工程,所以这里能够进行联调。

  1. 怎么让 Flutter 工程中的iOS工程运用本地编译好的引擎,需求在 Runner 的Generated.xcconfig 里边装备引擎
//编译引擎的途径
FLUTTER_ENGINE=/Users/zhou/engine_download/src
//对应的模拟器debug版本
LOCAL_ENGINE=ios_debug_sim_unopt

装备完成后就开端运转Runner工程,我在flutter 引擎里边在点击办法里边添加了一个打印

image

当我运转其他项目后,点击屏幕控制台输出了 点击了,这就说明晰挂载成功了

image
  1. 接下来联调 flutter tools ,需求在 Edit Configurations 里边 Program arguments 装备参数
run --local-engine-src-path /Users/zhou/engine_download/src --local-engine=ios_debug_sim_unopt

跑起来项目后,然后在 Xcode->Debug->Attach to process 里边附加工程,再打进入 /Users/zhou/engine_download/src/out/ios_debug_sim_unopt 翻开iOS工程,找到这个办法,这个便是咱们更新加载增量文件要调用的办法

image

在方才运转的Xcode工程里边添加断点

br set -n "IsolateGroupReloadContext::Reload"
image

这样就形成了一个闭环,引擎代码、Flutter 代码,flutter tools ,然后需改Flutter代码,在 flutter tools 里边履行 r ,发现Xcode断点到了 IsolateGroupReloadContext 这个办法开端履行添加烘托,说明验证了之前的热重载的步骤。

image

综合上文,就是flutter的热重载原理与工作流程解析;以及他的源码分析,更多flutter核心技术进阶可以查阅《flutter核心技术类目》里面板块技术三十几个模块。

总结

这样一步步的调试下来就能大概明白热重载的原理。Flutter 的热重载是基于 JIT 编译形式的代码增量同步。因为 JIT 属于动态编译,能够将 Dart 代码编译成生成中间代码,让 Dart VM 在运转时解说履行,因此能够经过动态更新中间代码完成增量同步。

另一方面,因为涉及到状况的保存与康复,涉及状况兼容与状况初始化的场景,热重载是无法支撑的,如改动前后 Widget 状况无法兼容、全局变量与静态特点的更改、main 办法里的更改、initState 办法里的更改、枚举和泛型的更改等。

能够发现,热重载提高了调试 UI 的功率,十分适合写界面款式这样需求反复检查修正作用的场景。但因为其状况保存的机制所限,热重载本身也有一些无法支撑的鸿沟。

上一篇下一篇

猜你喜欢

热点阅读