《Flutter技术解析与实战》读书笔记

第一章 混合工程

1. 混合工程下的Flutter研发结构

《Flutter技术解析与实战》读书笔记

2. 构建优化

问题:Android在FLutter启动是构建缓慢
解决:是工程应用Module对应的build.gradle位于android/app下

Native启动下的Flutter调试

iOS:使用Observatory
Android和iOS:使用IDE链接调试配置Dart Remote Debug
《Flutter技术解析与实战》读书笔记

Native启动下的Flutter热重载

启动App,进入Flutter页面后
iOS:查找Observatory端口x和认证码y,在flutter目录下,执行flutter attach --debug-uri=http://127.0.0.1:x/y/
Android:同上,也可以通过IDE Logcat或者ADB Logcat | grep Observatory获取端口,端口转发使用ADB forwart。

Native与Flutter 联合调试

Android:Android Studio 的Attach Debugger to Android Process 调试;
iOS:结合Xcode Attach 的Attach to Process;

3. 混合工程改造实践

混合开发模式

《Flutter技术解析与实战》读书笔记

依赖引入策略

本地依赖:同步方便,但耦合
远程依赖:减少耦合,同步繁琐

混合工程持续开发流程

《Flutter技术解析与实战》读书笔记

4. 混合技术方案

flutter-boot(混合开发的脚手架)

集成问题:

  1. 版本兼容问题
  2. 代码封装问题
  3. 原生接入繁琐

解决方案:

  1. Flutter引擎的托管
  2. 页面路由的配置
  3. 原生测试的跳转入口
FlutterBoost(混合栈框架升级)
混合方案基本原理:

Flutter技术链由C++实现的Flutter Engine和Dart实现Framework组成。Flutter Engine负责线程管理,Dart VM负责状态管理和Dart代码加载等工作。
一个进程里面最多只有一个Dart VM,但是一个进程可以由多个Flutter Engine,多个Engine实例共享一个Dart VM。

现有混合方案问题

单引擎:深度耦合,无法支持多个平级逻辑页面
《Flutter技术解析与实战》读书笔记
性能总结:Flutter View只有一个,每一个页面都是一个截图,如果Flutter页面多的情况下,则截图太多会占据大量内存,这里采用文件内存二级缓存策略,内存中只保存少量截图,按需加载,这样能在保证用户体验的同时内存维持在较为稳定的水平。
多引擎:

  • 冗余资源占据内存
  • 插件注册混乱
  • 增加通信复杂度
方案升级:FLutterBoost

《Flutter技术解析与实战》读书笔记

  • Container:容器,容纳Widget,是Navigator的派生类
  • Container Manager:Container管理者,提供show/remove等API
  • Coordinator:协调器,接受Messaging消息,负责调用Container Manager的状态管理。
  • Messaging:基于Channel的消息通信。
    原理解析:使用单引擎多Navigator对象管理模式,使用Key-Value映射扁平化的形式维护所有页面,不只有一个Navigator,使用多个Navigator对象维持多栈管理,实现多平行页面不丢失。

第二章 能力增强

2.1 基于原生能力的插件扩展

Flutter App调用Native APIs(Platform Channel)

《Flutter技术解析与实战》读书笔记
《Flutter技术解析与实战》读书笔记
《Flutter技术解析与实战》读书笔记

2.2 基于外接纹理的同层渲染

《Flutter技术解析与实战》读书笔记
Layer Tree:这个是dart runtime输出的一个树状数据结构,树上的每一个叶子节点,代表了一个界面元素(Button,Image等等)。
Skia:这个是谷歌的一个跨平台渲染框架,从目前IOS和anrdroid来看,SKIA底层最终都是调用OpenGL绘制。Vulkan支持还不太好,Metal还不支持。
Shell:这里的Shell特指平台特性(Platform)的那一部分,包含IOS和Android平台相关的实现,包括EAGLContext管理、上屏的操作以及后面将会重点介绍的外接纹理实现等等。
从图中可以看出,当Runtime完成Layout输出一个Layertree以后,在管线中会遍历Layertree的每一个叶子节点,每一个叶子节点最终会调用Skia引擎完成界面元素的绘制,在遍历完成后,在调用glPresentRenderBuffer(IOS)或者glSwapBuffer(Android)按完成上屏操作。
问题:Flutter在Native和Flutter Engine上实现了UI的隔离,书写UI代码时不用再关心平台实现从而实现了跨平台。但是Flutter想要获取一些Native侧的高内存占用图像(摄像头帧、视频帧、相册图片等等)会变得困难重重,前文说到的Channel用于消息传送,传输文件或图像会消耗巨大内存与CPU。

解决方案:外接纹理Texture

  1. FLutter渲染流程
    Native端的数据源(摄像头播放器等)将数据写入PixelBuffer,Flutter拿到之后转为OpenGLES Texture,交由Skia绘制。《Flutter技术解析与实战》读书笔记
  2. Flutter线程结构
    《Flutter技术解析与实战》读书笔记
    GPU Runner:负责GPU的渲染相关操作。
    IO Runner:负责资源的加载操作。
    Platform Runner:运行在main thread上,负责所有Native与Flutter Engine的交互。

《Flutter技术解析与实战》读书笔记
iOS通过两个线程各自使用自己的EAGLContext,彼此通过ShareGroup(android为shareContext)来共享纹理数据。

2.3 多媒体能力扩展实践

闲鱼相册组件API:
《Flutter技术解析与实战》读书笔记
Flutter层使用MVC架构;Native层由OpenGL负责BitMap转纹理。

2.4 富文本能力应用实践

Text:只能显示简单样式文本。
TextSpan:只能显示多重文本样式。

RichText

《Flutter技术解析与实战》读书笔记
通过TextPaint的Layout,在过程中通过TextSpan结构树,一次通过AddText添加各个阶段的文本,,最后通过Paragraph的Layout计算文本高度。
《Flutter技术解析与实战》读书笔记
再利用SpaceSpan记录宽高属性,和RichText结合可实现文案 图片 自定义控件融合起来,实现复杂效果。

第三章 业务架构设计

3.1 应用框架实践

Redux

  1. Redux可以做预测 集中式 易调试 灵活性的数据管理框架,所有对数据的“增删查改”等操作都由Redux集中负责。
  2. Redux 的概念是状态管理,那在已有 state 的基础上,为什么还需要 Redux ?因为使用 Redux 的好处是:共享状态和单一数据。
  3. Redux使用Middleware(AOP)模式和Subscribe机制,给框架带来灵活性和扩展性。
  4. Fish Redux通过Redux做集中化的可观察的数据管理,另外,在面向端侧FLutter页面纬度开发的场景中,通过一个组件需要定义一个数据(Sturct)和一个Reducer,通过组件之间存在者父依赖子的关系,解决“集中”和“分治”之间的矛盾,通过对Reducer的手动层层组装成改变为由框架自动完成,大大降低了使用Redux的工作。

3.2 轻量级动态化渲染引擎的设计

1. CodePush
2. 动态模版

《Flutter技术解析与实战》读书笔记

3.3 面向切面编程的设计实践

Dart语言特性: 1. Dart的反射支持很弱,只支持检查(Introspection),不支持修改(Modification);2. Flutter为了控制包大小,保证健壮性等原因,禁止了反射。
因此,Dart的AOP方案得基于编译期修改。

闲鱼AOP库:AspectD
  1. 无Before Around After三种语法,只有统一的抽象,Around。
  2. Call是调用点,Execute是执行点,Inject 的输入参数相对于 Call/Execute 而言,多了一个 lineNum 的命名参数,可用于指定插入逻辑的具体行号。

3.4 高性能的动态模版渲染实践