[Flutter] Flutter 的 build 系统

Posted bug樱樱

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Flutter] Flutter 的 build 系统相关的知识,希望对你有一定的参考价值。

前言

对于Flutter开发者来说,build_runner 可以说并不是一个陌生的东西,很多package中就要求调用build_runner 来自动生成处理代码,比如说json_serializable;

但正如其描述中所述的那样,其是通过 Dart Build System来实现的,build_runner 和其又是一个什么关系,接下来就来学习一下dart的build系统

dart 的 build 系统

组成

dart 的 build系统,由 build_configbuild_modulesbuild_resolversbuild_runnerbuild_testbuild_web_compilers 共同组合、完成了dart 的 build 系统;

  • build_config 就是解析那个build.yaml文件,用来配置build_runner,没什么好说的,具体的功能后面再细说;
  • build_modules 好像是解析module级别信息的一个库
  • build_resolvers 从自述文件中分析,好像是一个给build_runner 每步提供所需信息的解析器?
  • build_runner 整个build系统的核心部分,其他部分都是为了拓展和实现此功能而存在的;
  • build_test 字面意思,一个测试库;
  • build_web_compilers 用于web端的build系统;

作用

Flutter的build系统其实就是生成代码,对标的应该是JAVA的APT这块的东西;

另外,对于 dart 的 build 系统,官方是有这么一段介绍:

Although the Dart build system is a good alternative to reflection (which has performance issues) and macros (which Dart’s compilers don’t support), it can do more than just read and write Dart code. For example, the sass_builder package implements a builder that generates .css files from .scss and .sass files.

也就是说dart build理论上是可以来做很多人心心念念的反射的;

基本使用

如果仅仅是使用方面来说,build_runner 的使用非常简单;比如说我们最常用的一条命令就是:

flutter pub run build_runner build

也可以配置build.yaml来修改配置信息,生成符合需要的代码;

不过在输入上面那句build_runner build之后发生了什么,像build_config之类的在这个过程中各自起了什么作用,这就需要追踪一下;

build_runner 都干了什么

根据日志信息,build_runner 的流程基本遵循这样一个套路:

  • 生成和预编译build脚本
  • 处理输入环境和资源
  • 根据前面的脚本和输入信息,开始正式执行builder生成代码;
  • 缓存信息,用于下一回生成代码的时候增量判断使用;

接下来就看下这些编译脚本、输入环境、资源等不知所云的东西,到底是什么;

生成和预编译build脚本

生成部分:

首先来到build_runner的main函数部分,前面一大片对参数检测的拦截判断,真正执行命令的地方放在了最后:

在这个方法中最先做的事就是生成build脚本

其内容也很简单,说白了就是输出一个文件而已:

至于这个文件内容是什么,有什么用,先放到后面再说;现在先关注于整体流程;

那么现在可以得知,这步会在scriptLocaton这个路径上生成一个build脚本;而这个路径也不难得到:

其实就是 .dart_tool/build/entrypoint/build.dart 这个文件;

预编译部分:

在上面贴的generateAndRun方法中,生成文件之后就会执行一个 _createKernelIfNeeded 方法,其作用也正如其名,检测是否需要就创建内核文件;

而这个内核文件,也就是后缀为build.dart.dill 文件

同时,在这里也提到了一个新的概念:assetGraph,不过这些也是后面再细看的东西;

处理输入环境和资源

在编译完build脚本生成内核后,下面就是执行这个内核文件;在这里新开了一个isolate去执行这个文件:

接下来就该看下这个内核文件到底是什么……但是呢,内核文件这东西,本来就不是给人看的………………所以呢,可以从另一方面考虑下,比如说,既然内核文件看不了,那我就看内核文件的从哪编译来的,反正逻辑上也是大差不差,完全可以参考;

正好内核文件的来源,也就是那个build脚本,其位置在上面也提到过了;在我测试代码中,它最后是这样的:

其中的这个_i10,正是build_runner……看来兜兜转转又回来了?

应该说回来了,但没完全回来,上面提到的build_runner是bin目录下的;这次的build_runner是lib目录下的,入口还是不一样的;

在这里,build_runner build中的build这个参数才真正识别并开始执行;前面都是前戏;而执行这个build命令的是一个名为BuildCommandRunner的类,其内部内置了包括build在内的诸多函数命令:

由于测试的指令参数为build,所以命中的commend为 BuildCommand;而 BuildCommand 所做的事也基本集中在 src/generate/build.dart 这个文件中的build方法中了;自此开始真正去执行build_runner对应Builder中要求做的事;

其build方法所做的事还是比较容易看懂的:

  1. 配置环境(包括输入输出配置)
  2. 配置通用选项(build时候的配置项目)
  3. 调用BuildRunner.create创建Builder和生成所需数据,最后调用run执行;

而这部分所说的处理输入环境和资源就在 BuildRunner.create 这部分中;其会调用 BuildDefinition.prepareWorkspace方法;

而在这里就出现了上面提到的assetGraph,这里就是其创建和使用的地方:

所以,最终总结一下,处理输入环境和资源 这个环节所做的事就是根据配置生成输入输出、build过程中所需的各种参数,提供assetGraph这个东西;

具体这些配置入口在哪,从何而来,assetGraph又是什么东西,有什么作用,后面再看;

正式执行builder生成代码

这部分就是刚才提到的调用run方法的地方;

它的run方法咋看好像也不难懂的样子,主要是各种新名词有点多:

不过现在只跟随build流程来说的话,核心应该事其中的_safeBuild方法:

其所做的事,除了各种心跳log之外,应该就是更新assetGraph;执行_runPhases;另外毕竟事safeBuild嘛,所以新开了一个zone来处理;

_runPhases所做的事就是真正去执行build所做的事,生成代码之类的;比如说json_serializable中的build,就会走_runBuilder部分并最终调用runBuilder中的builder.build,也就是自定义Builder中需要自己实现的部分;

对了,关于像json_serializable的自定义Builder从何而来的问题,答案是一开始就已经集成进来了,在builder.dart中已经出现了其身影:

不过为什么build.dart 能得知具体有哪些builder?比如说json_serializable中的builder,是怎么加入到build.dart中的,那也是后面要看的东西;

缓存信息

再次回到 _safeBuild 这块,缓存信息的部分紧贴着run部分:

好像就写了一下文件,没了?

结语

这篇大体粗略的过了一下build这个命令都干了什么;不过像生成的文件内部结构、作用;配置信息来源,如何解析之类的问题还未解决;在后面会依次看看;

最后尝试实现一份自己的自定义Builder;

作者:lwlizhe
链接:https://juejin.cn/post/7133488621180420126

最后

如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。

如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。

相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。

一、架构师筑基必备技能

1、深入理解Java泛型
2、注解深入浅出
3、并发编程
4、数据传输与序列化
5、Java虚拟机原理
6、高效IO
……

二、Android百大框架源码解析

1.Retrofit 2.0源码解析
2.Okhttp3源码解析
3.ButterKnife源码解析
4.MPAndroidChart 源码解析
5.Glide源码解析
6.Leakcanary 源码解析
7.Universal-lmage-Loader源码解析
8.EventBus 3.0源码解析
9.zxing源码分析
10.Picasso源码解析
11.LottieAndroid使用详解及源码解析
12.Fresco 源码分析——图片加载流程

三、Android性能优化实战解析

  • 腾讯Bugly:对字符串匹配算法的一点理解
  • 爱奇艺:安卓APP崩溃捕获方案——xCrash
  • 字节跳动:深入理解Gradle框架之一:Plugin, Extension, buildSrc
  • 百度APP技术:Android H5首屏优化实践
  • 支付宝客户端架构解析:Android 客户端启动速度优化之「垃圾回收」
  • 携程:从智行 Android 项目看组件化架构实践
  • 网易新闻构建优化:如何让你的构建速度“势如闪电”?

四、高级kotlin强化实战

1、Kotlin入门教程
2、Kotlin 实战避坑指南
3、项目实战《Kotlin Jetpack 实战》

  • 从一个膜拜大神的 Demo 开始

  • Kotlin 写 Gradle 脚本是一种什么体验?

  • Kotlin 编程的三重境界

  • Kotlin 高阶函数

  • Kotlin 泛型

  • Kotlin 扩展

  • Kotlin 委托

  • 协程“不为人知”的调试技巧

  • 图解协程:suspend

五、Android高级UI开源框架进阶解密

1.SmartRefreshLayout的使用
2.Android之PullToRefresh控件源码解析
3.Android-PullToRefresh下拉刷新库基本用法
4.LoadSir-高效易用的加载反馈页管理框架
5.Android通用LoadingView加载框架详解
6.MPAndroidChart实现LineChart(折线图)
7.hellocharts-android使用指南
8.SmartTable使用指南
9.开源项目android-uitableview介绍
10.ExcelPanel 使用指南
11.Android开源项目SlidingMenu深切解析
12.MaterialDrawer使用指南

六、NDK模块开发

1、NDK 模块开发
2、JNI 模块
3、Native 开发工具
4、Linux 编程
5、底层图片处理
6、音视频开发
7、机器学习

七、Flutter技术进阶

1、Flutter跨平台开发概述
2、Windows中Flutter开发环境搭建
3、编写你的第一个Flutter APP
4、Flutter开发环境搭建和调试
5、Dart语法篇之基础语法(一)
6、Dart语法篇之集合的使用与源码解析(二)
7、Dart语法篇之集合操作符函数与源码分析(三)

八、微信小程序开发

1、小程序概述及入门
2、小程序UI开发
3、API操作
4、购物商场项目实战……

全套视频资料:

一、面试合集

二、源码解析合集


三、开源框架合集


欢迎大家一键三连支持,若需要文中资料,直接点击文末CSDN官方认证微信卡片免费领取↓↓↓

以上是关于[Flutter] Flutter 的 build 系统的主要内容,如果未能解决你的问题,请参考以下文章

Flutter 在执行 Flutter build ios 后卡在 Building Dart 代码上

在 Flutter 中发布的“flutter build apk”出现错误

如何解决flutter gradle build error?C:\flutter\packages\flutter_tools\gradle\flutter.gradle' line: 991

Flutter:build/app/outputs下的apk/release目录和flutter-apk目录有啥区别?

解决Flutter升级后,flutter run 卡在gradle build running的问题

Flutter 应用程序不是由 Flutter build ios 运行,而是由 xcode 运行