Flutter框架源码深度分析

1. 引擎架构与渲染管线

1.1 Flutter引擎架构

Flutter引擎架构采用分层设计,从底层到顶层包括:

+-------------------------+
|       Dart Framework    |  <- 用户使用的Flutter框架(Material, Cupertino等)
+-------------------------+
|       Flutter Engine    |  <- 渲染引擎(Skia)、平台通道、Dart VM
+-------------------------+
|    Embedder (Platform)  |  <- 平台特定嵌入层(Android/iOS/Web等)
+-------------------------+

Flutter引擎的C++代码主要位于engine/src目录下,核心组件包括:

  • Shell: 引擎的外壳,负责协调各个子系统
  • Dart VM: 执行Dart代码的虚拟机
  • Skia: 跨平台2D渲染引擎
  • Text: 文本渲染引擎
  • Platform Channels: 平台通道,用于Flutter与原生平台通信

Shell是Flutter引擎的主要入口点,在Android平台上通过FlutterActivityFlutterView启动,在iOS平台上通过FlutterViewController启动。

关键代码: Shell初始化

// engine/src/flutter/shell/common/shell.cc
Shell::Shell(DartVMRef vm, TaskRunners task_runners, Settings settings)
    : task_runners_(std::move(task_runners)),
      settings_(std::move(settings)),
      vm_(std::move(vm)),
      weak_factory_(this) {
  FML_DCHECK(task_runners_.IsValid());
  FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());

  // Initialize the engine components.
  service_protocol_handler_ = std::make_unique<ServiceProtocolHandler>(
      task_runners_.GetUITaskRunner(),
      task_runners_.GetIOTaskRunner(),
      task_runners_.GetPlatformTaskRunner(),
      this);

  // 创建引擎实例
  engine_ = std::make_unique<Engine>(
      *this,
      /*delegate=*/nullptr,
      /*snapshot_delegate=*/nullptr,
      /*io_manager=*/nullptr,
      /*unref_queue=*/nullptr,
      task_runners_,
      settings_,
      std::move(vm_));

  display_manager_ = std::make_unique<DisplayManager>();
}

Flutter引擎的生命周期主要由以下几个阶段组成:

  1. 初始化: 创建Shell和Engine实例
  2. 运行: 执行Dart代码,处理渲染和事件
  3. 销毁: 清理资源

1.2 Skia渲染引擎

Flutter使用Google的Skia引擎作为其2D渲染引擎,Skia是一个开源的跨平台2D图形库,提供了统一的API来绘制文本、几何图形和图像。

Skia渲染过程主要包含以下核心对象:

  • SkCanvas: 提供绘制操作的接口
  • SkPaint: 定义如何绘制(颜色、样式、字体等)
  • SkPath: 定义要绘制的形状
  • SkPicture: 记录绘制命令的序列,可回放

Flutter通过ui.Canvas类封装了Skia的SkCanvas接口,提供给Dart层使用:

// 在Flutter的Dart代码中,Canvas类是对Skia的SkCanvas的封装
// flutter/lib/ui/painting.dart
class Canvas extends NativeFieldWrapperClass2 {
  // Native方法,调用Skia的drawRect方法
  void drawRect(Rect rect, Paint paint) {
    _drawRect(rect.left, rect.top, rect.right, rect.bottom, paint);
  }

  // 底层Native实现
  <Void Function(Pointer<Void>, Double, Double, Double, Double, Pointer<Void>)>(symbol: 'Canvas_drawRect')
  external void _drawRect(double left, double top, double right, double bottom, Paint paint);
}

底层C++实现在engine/src/flutter/lib/ui/painting/canvas.cc:

void Canvas::drawRect(double left, double top, double right, double bottom,
                      const Paint& paint) {
  SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
  SkiaObjectStore::DartWrappable::AssertDartObjectNotCollected(paint);
  canvas_->drawRect(rect, *paint.paint());
}

1.3 渲染管线完整流程

Flutter的渲染管线是一个复杂的流程,从Dart层到GPU渲染,完整的渲染管线如下图所示:

+------------------+     +------------------+     +------------------+
|   Dart UI代码    |---->|   Widget树构建   |---->|   Element树更新  |
+------------------+     +------------------+     +------------------+
        |                                                |
        v                                                v
+------------------+     +------------------+     +------------------+
|  RenderObject树  |<----|  布局与绘制阶段  |---->|    图层树构建    |
+------------------+     +------------------+     +------------------+
        |                                                |
        v                                                v
+------------------+     +------------------+     +------------------+
|  Skia绘制命令    |---->|   合成与光栅化   |---->|    GPU渲染      |
+------------------+     +------------------+     +------------------+

详细的渲染流程如下:

  1. UI构建阶段:

    • 用户的build方法返回Widget树
    • Element树根据Widget树更新
    • Element树创建/更新RenderObject树
  2. 布局阶段:

    • 从RenderObject树的根节点开始,自上而下传递约束
    • 从叶节点开始,自下而上计算并返回尺寸
  3. 绘制阶段:

    • 创建LayerTree(图层树)
    • RenderObject调用paint方法,将绘制命令记录到适当的Layer中
  4. 合成与光栅化:

    • LayerTree传递给Flutter引擎
    • 引擎将LayerTree转换为Skia绘制命令
    • Skia执行光栅化,生成位图
  5. 渲染到屏幕:

    • GPU将光栅化后的内容渲染到屏幕上

关键代码: 渲染流程触发

// packages/flutter/lib/src/rendering/binding.dart
mixin RendererBinding on BindingBase, ServicesBinding, SchedulerBinding {
  
  void drawFrame() {
    assert(renderView != null);
    pipelineOwner.flushLayout();         // 执行布局
    pipelineOwner.flushCompositingBits();// 确定哪些需要自己的层
    pipelineOwner.flushPaint();          // 执行绘制
    renderView.compositeFrame();         // 发送场景到GPU
  }
}

底层实现: 合成帧并发送到GPU

// engine/src/flutter/flow/layers/layer_tree.cc
void LayerTree::Paint() const {
  SkCanvas* canvas = frame_->SkiaCanvas();
  canvas->clear(SK_ColorTRANSPARENT);

  // 遍历图层树进行绘制
  Layer::PrerollContext context = {
      frame_->raster_cache(),
      frame_->GetGrDirectContext(),
      frame_->GetSceneUpdateContext(),
      mutators_stack_,
      checkerboard_offscreen_layers_,
  };
  root_layer_->Preroll(&context, frame_->GetRootTransformation());

  // 绘制图层
  Layer::PaintContext paint_context = {
      canvas,
      frame_->GetGrDirectContext(),
      frame_->raster_cache(),
      checkerboard_offscreen_layers_,
  };
  root_layer_->Paint(&paint_context);
}

1.4 Dart与C++层交互

Flutter框架中Dart与C++交互主要通过FFI(Foreign Function Interface)和Embedder API实现。

Dart与C++通信的三种主要方式:

  1. Method Channel: 异步通信,用于Flutter与平台特定代码交互
  2. Dart FFI: 直接调用本地函数,性能更高
  3. Native Bindings: 基于FFI的更高级别封装

Method Channel示例:

// Dart端代码
const platform = MethodChannel('samples.flutter.dev/battery');

// 调用平台特定代码
final int batteryLevel = await platform.invokeMethod('getBatteryLevel');
// Android端代码
new MethodChannel(flutterView, "samples.flutter.dev/battery").setMethodCallHandler(
  (call, result) -> {
    if (call.method.equals("getBatteryLevel")) {
      int batteryLevel = getBatteryLevel();
      result.success(batteryLevel);
    } else {
      result.notImplemented();
    }
  }
);

底层实现: Dart FFI调用原生方法

// Dart FFI调用
import 'dart:ffi';

// 定义C函数签名
typedef NativeAddFunc = Int32 Function(Int32 a, Int32 b);
// 定义对应的Dart函数签名
typedef AddFunc = int Function(int a, int b);

void main() {
  // 加载动态库
  final dylib = DynamicLibrary.open('path/to/library.so');

  // 查找函数符号
  final addFunc = dylib.lookupFunction<NativeAddFunc, AddFunc>('add');

  // 调用函数
  print('3 + 5 = ${addFunc(3, 5)}');
}

C++实现:

// C++实现
extern "C" {
  JNIEXPORT int32_t JNICALL
  Java_com_example_NativeLib_add(JNIEnv* env, jobject thiz, jint a, jint b) {
    return a + b;
  }
}

绘制命令如何从Dart传递到Skia:

Flutter中的绘制命令通过一系列的层(Layer)和对象将Dart层的UI描述转换为Skia的绘制命令。

// Dart层的绘制命令
canvas.drawRect(
  Rect.fromLTWH(20.0, 20.0, 100.0, 100.0),
  Paint()..color = Colors.blue
);

这个调用通过FFI传递到C++层:

// engine/src/flutter/lib/ui/painting/canvas.cc
void Canvas::drawRect(double left, double top, double right, double bottom,
                      const Paint& paint) {
  SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
  SkiaObjectStore::DartWrappable::AssertDartObjectNotCollected(paint);
  canvas_->drawRect(rect, *paint.paint());
}

最终由Skia执行实际的绘制:

// Skia内部实现(简化版)
void SkCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) {
    // 将矩形添加到绘制列表
    this->getDevice()->drawRect(rect, paint);
}

2. 核心对象模型与树结构

2.1 Widget树详解

Widget是Flutter UI的核心概念,是UI元素的不可变描述。Widget是轻量级对象,可以频繁地重建。

Widget类的核心源码:

// packages/flutter/lib/src/widgets/framework.dart

abstract class Widget extends DiagnosticableTree {
  const Widget({ this.key });

  final Key? key;

  
  Element createElement();

  
  String toStringShort() {
    final String type = objectRuntimeType(this, 'Widget');
    return key == null ? type : '$type-$key';
  }

  
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.defaultDiagnosticsTreeStyle = DiagnosticsTreeStyle.dense;
  }

  // 判断是否需要更新Element
  static bool canUpdate(Widget oldWidget, Widget newWidget) {
    return oldWidget.runtimeType == newWidget.runtimeType
        && oldWidget.key == newWidget.key;
  }
}

Widget分为三大类:

  1. StatelessWidget: 无状态Widget,一旦创建不会改变
  2. StatefulWidget: 有状态Widget,可以在生命周期内改变
  3. RenderObjectWidget: 直接创建RenderObject的Widget

StatelessWidget源码:

// packages/flutter/lib/src/widgets/framework.dart
abstract class StatelessWidget extends Widget {
  const StatelessWidget({ Key? key }) : super(key: key);

  
  StatelessElement createElement() => StatelessElement(this);

  
  Widget build(BuildContext context);
}

StatefulWidget源码:

// packages/flutter/lib/src/widgets/framework.dart
abstract class StatefulWidget extends Widget {
  const StatefulWidget({ Key? key }) : super(key: key);

  
  StatefulElement createElement() => StatefulElement(this);

  
  State createState();
}

Widget树的构建:

Flutter应用的UI是通过嵌套Widget构建的树状结构。下面是一个简单的Widget树示例:

MaterialApp(
  home: Scaffold(
    appBar: AppBar(
      title: Text('Flutter Demo'),
    ),
    body: Center(
      child: Column(
        children: [
          Text('Hello'),
          ElevatedButton(
            onPressed: () {},
            child: Text('Click me'),
          ),
        ],
      ),
    ),
  ),
)

这个Widget树的层次结构:

MaterialApp
└── Scaffold
    ├── AppBar
    │   └── Text
    └── Center
        └── Column
            ├── Text
            └── ElevatedButton
                └── Text

Widget树的构建是通过各个Widget的build方法递归完成的。例如:

class MyWidget extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Container(
      child: Text('Hello'),
    );
  }
}

在内部,Flutter会调用这个build方法来获取子Widget。

2.2 Element树与重建机制

Element是Widget的实例,负责管理Widget与RenderObject之间的关系。Element树是实际构建的UI树,而Widget树只是一个配置。

Element类的核心源码:

// packages/flutter/lib/src/widgets/framework.dart
abstract class Element extends DiagnosticableTree implements BuildContext {
  Element(Widget widget)
    : _widget = widget;

  Widget _widget;

  
  Widget get widget => _widget;

  // 元素的状态
  bool _active = false;
  bool get active => _active;

  // 是否需要重建
  bool _dirty = true;
  bool get dirty => _dirty;

  // 挂载元素
  
  void mount(Element? parent, Object? newSlot) {
    _parent = parent;
    _slot = newSlot;
    _depth = _parent != null ? _parent!._depth + 1 : 1;
    _active = true;
    // 将自己添加到全局键的注册表中(如果有GlobalKey)
    if (widget.key is GlobalKey) {
      final GlobalKey globalKey = widget.key as GlobalKey;
      _registerGlobalKey(globalKey, this);
    }
    // 初始化插槽
    _updateInheritance();
  }

  // 更新Widget
  
  void update(covariant Widget newWidget) {
    // 更新widget引用
    _widget = newWidget;
    // 标记为需要重建
    markNeedsBuild();
  }

  // 标记需要重建
  void markNeedsBuild() {
    if (!_active)
      return;
    if (_dirty)
      return;
    _dirty = true;
    owner!.scheduleBuildFor(this);
  }

  // 重建元素
  void rebuild() {
    if (!_active || !_dirty)
      return;
    performRebuild();
  }

  
  void performRebuild();
}

Element的三个主要子类:

  1. ComponentElement: 用于复合Widget,如StatelessWidget和StatefulWidget
  2. RenderObjectElement: 与RenderObject关联的Element
  3. StatefulElement: 为StatefulWidget创建并管理State对象

ComponentElement源码:

// packages/flutter/lib/src/widgets/framework.dart
abstract class ComponentElement extends Element {
  ComponentElement(Widget widget) : super(widget);

  Element? _child;

  
  void performRebuild() {
    Widget built;
    try {
      // 调用build方法构建子Widget
      built = build();
    } catch (e, stack) {
      // 处理构建过程中的错误
    }
    try {
      // 更新子Element
      _child = updateChild(_child, built, slot);
    } catch (e, stack) {
      // 处理更新过程中的错误
    }

    // 标记为不需要重建
    _dirty = false;
  }

  
  Widget build();

  
  void unmount() {
    // 卸载子元素
    _child = updateChild(_child, null, slot);
    super.unmount();
  }
}

StatefulElement源码:

// packages/flutter/lib/src/widgets/framework.dart
class StatefulElement extends ComponentElement {
  StatefulElement(StatefulWidget widget)
      : state = widget.createState(),
        super(widget) {
    state._element = this;
    state._widget = widget;
  }

  
  Widget build() => state.build(this);

  final State state;

  
  void update(StatefulWidget newWidget) {
    final StatefulWidget oldWidget = widget as StatefulWidget;
    // 更新widget引用
    super.update(newWidget);
    final State state = this.state;
    final bool oldWidgetWasRebuilt = _debugIsWidgetRebuilt(oldWidget);
    // 更新state的widget引用
    state._widget = newWidget;
    // 调用state的didUpdateWidget方法
    if (!oldWidgetWasRebuilt)
      state.didUpdateWidget(oldWidget);
    // 标记为需要重建
    _dirty = true;
    // 重建state
    rebuild();
  }
}

Element树的重建机制:

Element树的重建是通过markNeedsBuildperformRebuild方法协同完成的。

重建流程:

  1. 调用setState标记Element为dirty
  2. 将Element添加到BuildOwner的脏Element列表
  3. 在下一帧,BuildOwner遍历脏Element列表,调用它们的rebuild方法
  4. rebuild方法调用performRebuild,后者会构建新的Widget并更新子Element
// packages/flutter/lib/src/widgets/binding.dart
void drawFrame() {
  try {
    if (renderViewElement != null)
      buildOwner!.buildScope(renderViewElement!);
    super.drawFrame();
    buildOwner!.finalizeTree();
  } finally {
    // ...
  }
}
// packages/flutter/lib/src/widgets/framework.dart
void buildScope(Element context, [VoidCallback? callback]) {
  if (callback != null) {
    Timeline.startSync('Build', arguments: timelineWhitelistArguments);
    try {
      callback();
    } finally {
      Timeline.finishSync();
    }
  }

  // 排序脏元素(按深度升序)
  _dirtyElements.sort(Element._sort);

  // 构建所有脏元素
  int dirtyCount = _dirtyElements.length;
  int index = 0;
  while (index < dirtyCount) {
    final Element element = _dirtyElements[index];
    // 如果元素还是脏的且活跃的,则重建它
    if (element._dirty && element.active) {
      element.rebuild();
    }
    index += 1;
  }

  // 清空脏元素列表
  _dirtyElements.clear();
}

2.3 RenderObject树与布局渲染

RenderObject树是实际负责布局和绘制的树结构,每个RenderObject对应屏幕上的一个可视元素。

RenderObject类的核心源码:

// packages/flutter/lib/src/rendering/object.dart
abstract class RenderObject extends AbstractNode with DiagnosticableTreeMixin implements HitTestTarget {
  // 父级数据
  ParentData? parentData;

  // 约束
  Constraints? _constraints;
  Constraints get constraints => _constraints!;

  // 是否需要布局
  bool _needsLayout = true;
  bool get needsLayout => _needsLayout;

  // 是否需要绘制
  bool _needsPaint = true;
  bool get needsPaint => _needsPaint;

  // 执行布局
  void layout(Constraints constraints, { bool parentUsesSize = false }) {
    // 检查约束是否变化
    bool constraintsChanged = _constraints == null || constraints != _constraints;

    // 设置新约束
    _constraints = constraints;

    // 如果需要布局或约束变化,执行布局
    if (_needsLayout || constraintsChanged) {
      _needsLayout = false;
      performLayout();
      markNeedsSemanticsUpdate();
    }
  }

  // 布局方法(子类实现)
  void performLayout();

  // 标记需要布局
  void markNeedsLayout() {
    if (_needsLayout) {
      return;
    }

    // 标记为需要布局
    _needsLayout = true;

    // 如果有父级,通知父级
    if (parent is RenderObject) {
      final RenderObject parent = this.parent! as RenderObject;
      if (!_relayoutBoundary) {
        parent.markNeedsLayout();
        return;
      }

      // 如果是布局边界,将自己添加到管道所有者的_nodesNeedingLayout列表
      owner!._nodesNeedingLayout.add(this);
      owner!.requestVisualUpdate();
    }
  }

  // 标记需要绘制
  void markNeedsPaint() {
    if (_needsPaint)
      return;
    _needsPaint = true;

    // 将自己添加到管道所有者的_nodesNeedingPaint列表
    if (isRepaintBoundary && attached) {
      owner!._nodesNeedingPaint.add(this);
      owner!.requestVisualUpdate();
    } else if (parent is RenderObject) {
      final RenderObject parent = this.parent! as RenderObject;
      parent.markNeedsPaint();
    }
  }

  // 绘制方法(子类实现)
  void paint(PaintingContext context, Offset offset);
}

RenderObject有多个子类,其中最常用的是RenderBox,它处理矩形布局:

RenderBox源码:

// packages/flutter/lib/src/rendering/box.dart
abstract class RenderBox extends RenderObject {
  // 尺寸
  Size _size = Size.zero;
  Size get size => _size;

  // 布局子级
  void layoutChild(RenderBox child, BoxConstraints constraints) {
    child.layout(constraints, parentUsesSize: true);
  }

  // 子级的尺寸
  Size childSize(RenderBox child) {
    return child.size;
  }

  // 命中测试
  bool hitTest(BoxHitTestResult result, { required Offset position }) {
    if (_size.contains(position)) {
      if (hitTestChildren(result, position: position) || hitTestSelf(position)) {
        result.add(BoxHitTestEntry(this, position));
        return true;
      }
    }
    return false;
  }

  // 命中测试自身(子类实现)
  bool hitTestSelf(Offset position) => false;

  // 命中测试子级(子类实现)
  bool hitTestChildren(BoxHitTestResult result, { required Offset position }) => false;
}

布局过程:

RenderObject的布局过程是从根节点自上而下进行的:

  1. 父节点调用子节点的layout方法,传递约束
  2. 子节点计算自己的大小,可能会根据需要调用其子节点的layout方法
  3. 子节点将自己的尺寸返回给父节点

例如,RenderFlex(用于Row和Column)的布局过程:

// packages/flutter/lib/src/rendering/flex.dart

void performLayout() {
  // 首先确定主轴和交叉轴
  final BoxConstraints constraints = this.constraints;

  // 计算交叉轴约束
  final BoxConstraints innerConstraints;
  if (crossAxisAlignment == CrossAxisAlignment.stretch) {
    innerConstraints = BoxConstraints.tightFor(
      width: direction == Axis.horizontal ? null : constraints.maxWidth,
      height: direction == Axis.horizontal ? constraints.maxHeight : null,
    );
  } else {
    innerConstraints = BoxConstraints(
      maxWidth: direction == Axis.horizontal ? double.infinity : constraints.maxWidth,
      maxHeight: direction == Axis.horizontal ? constraints.maxHeight : double.infinity,
    );
  }

  // 第一遍:确定非弹性子级的大小
  double mainAxisExtent = 0.0;
  double crossAxisExtent = 0.0;

  RenderBox? child = firstChild;
  while (child != null) {
    final FlexParentData childParentData = child.parentData! as FlexParentData;

    // 布局子级
    child.layout(innerConstraints, parentUsesSize: true);

    // 更新主轴和交叉轴的大小
    final double childMainAxisExtent = _getMainAxisExtent(child);
    final double childCrossAxisExtent = _getCrossAxisExtent(child);

    mainAxisExtent += childMainAxisExtent;
    crossAxisExtent = math.max(crossAxisExtent, childCrossAxisExtent);

    child = childParentData.nextSibling;
  }

  // 设置自己的大小
  final double allocatedSize;
  if (direction == Axis.horizontal) {
    size = constraints.constrain(Size(mainAxisExtent, crossAxisExtent));
    allocatedSize = size.width;
  } else {
    size = constraints.constrain(Size(crossAxisExtent, mainAxisExtent));
    allocatedSize = size.height;
  }

  // 第二遍:根据主轴方向和对齐方式调整子级位置
  final double actualSize = allocatedSize - mainAxisExtent;
  double actualSizeDelta = 0.0;

  // 根据mainAxisAlignment确定子元素的位置
  switch (mainAxisAlignment) {
    case MainAxisAlignment.start:
      leadingSpace = 0.0;
      betweenSpace = 0.0;
      break;
    case MainAxisAlignment.end:
      leadingSpace = actualSize;
      betweenSpace = 0.0;
      break;
    case MainAxisAlignment.center:
      leadingSpace = actualSize / 2.0;
      betweenSpace = 0.0;
      break;
    case MainAxisAlignment.spaceBetween:
      leadingSpace = 0.0;
      betweenSpace = childCount > 1 ? actualSize / (childCount - 1) : 0.0;
      break;
    case MainAxisAlignment.spaceAround:
      betweenSpace = childCount > 0 ? actualSize / childCount : 0.0;
      leadingSpace = betweenSpace / 2.0;
      break;
    case MainAxisAlignment.spaceEvenly:
      betweenSpace = childCount > 0 ? actualSize / (childCount + 1) : 0.0;
      leadingSpace = betweenSpace;
      break;
  }

  // 设置子级位置
  double childMainPosition = leadingSpace;
  child = firstChild;
  while (child != null) {
    final FlexParentData childParentData = child.parentData! as FlexParentData;

    // 设置子级的位置
    if (direction == Axis.horizontal) {
      childParentData.offset = Offset(childMainPosition, 0.0);
    } else {
      childParentData.offset = Offset(0.0, childMainPosition);
    }

    childMainPosition += _getMainAxisExtent(child) + betweenSpace;

    child = childParentData.nextSibling;
  }
}

2.4 三棵树的协同与转换

Flutter的渲染过程涉及三棵树的协作:

  1. Widget树: 描述UI的配置
  2. Element树: 管理Widget的实例和生命周期
  3. RenderObject树: 处理布局和绘制

这三棵树的关系可以用下图表示:

+------------------+     +------------------+     +------------------+
|    Widget树      |---->|    Element树     |---->|  RenderObject树  |
|   (配置描述)     |     |  (结构和状态)    |     |  (布局和渲染)    |
+------------------+     +------------------+     +------------------+

Widget → Element的转换:

通过createElement方法,Widget创建对应的Element:

// StatelessWidget创建StatelessElement

StatelessElement createElement() => StatelessElement(this);

// StatefulWidget创建StatefulElement

StatefulElement createElement() => StatefulElement(this);

// RenderObjectWidget创建RenderObjectElement

RenderObjectElement createElement() => RenderObjectElement(this);

Element → RenderObject的转换:

RenderObjectElement通过createRenderObject方法创建RenderObject:

// packages/flutter/lib/src/widgets/framework.dart
abstract class RenderObjectWidget extends Widget {
  const RenderObjectWidget({ Key? key }) : super(key: key);

  
  RenderObject createRenderObject(BuildContext context);

  
  void updateRenderObject(BuildContext context, covariant RenderObject renderObject) { }
}

class RenderObjectElement extends Element {
  RenderObjectElement(RenderObjectWidget widget) : super(widget);

  
  void mount(Element? parent, Object? newSlot) {
    super.mount(parent, newSlot);
    _renderObject = widget.createRenderObject(this);
    attachRenderObject(newSlot);
    _dirty = false;
  }

  
  void update(covariant RenderObjectWidget newWidget) {
    super.update(newWidget);
    widget.updateRenderObject(this, renderObject);
  }
}

更新流程:

当状态变化时,三棵树的更新流程如下:

  1. 调用setState,标记Element为dirty
  2. 在下一帧,BuildOwner遍历脏Element,调用它们的rebuild方法
  3. Element重建并对比新旧Widget树,确定哪些Element需要更新或替换
  4. 更新RenderObject树,调用需要重新布局或绘制的RenderObject的方法
// 状态更新触发流程
void setState(VoidCallback fn) {
  // 执行状态更新函数
  fn();
  // 标记Element需要重建
  _element.markNeedsBuild();
}

// Element标记为需要重建
void markNeedsBuild() {
  // 已经标记为dirty,直接返回
  if (_dirty)
    return;
  _dirty = true;
  // 将Element添加到BuildOwner的待重建列表
  owner.scheduleBuildFor(this);
}

// BuildOwner调度重建
void scheduleBuildFor(Element element) {
  // 将Element添加到待重建列表
  _dirtyElements.add(element);
  // 请求下一帧
  scheduleFrame();
}

案例: Text Widget到屏幕渲染的全过程

以Text组件为例,展示从Widget到屏幕渲染的完整过程:

  1. 创建Widget:
Text('Hello, Flutter!')
  1. 创建Element:
// packages/flutter/lib/src/widgets/text.dart

RenderObjectElement createElement() => _TextElement(this);
  1. 创建RenderObject:
// packages/flutter/lib/src/widgets/text.dart

RenderParagraph createRenderObject(BuildContext context) {
  return RenderParagraph(
    _textSpan,
    textDirection: textDirection,
    textAlign: textAlign,
    // ... 其他参数
  );
}
  1. 布局阶段:
// packages/flutter/lib/src/rendering/paragraph.dart

void performLayout() {
  // 创建文本布局器
  _layoutTextWithConstraints(constraints);

  // 设置大小
  size = constraints.constrain(_textPainter.size);
}
  1. 绘制阶段:
// packages/flutter/lib/src/rendering/paragraph.dart

void paint(PaintingContext context, Offset offset) {
  // 绘制文本
  _textPainter.paint(context.canvas, offset);
}

这样,Text Widget最终被渲染到屏幕上,完成了从Widget到像素的转换过程。

3. 布局系统深度剖析

3.1 约束传递机制

Flutter的布局系统采用约束传递机制,这种机制从父级向子级传递约束,从子级向父级回传尺寸。

约束传递的基本过程:

父Widget → 父RenderObject → 子RenderObject → 子Widget
  (传递约束)                 (回传尺寸)

约束的核心概念:

Flutter中有两种主要的约束类型:

  1. BoxConstraints: 用于矩形布局,定义了最小和最大宽高
  2. SliverConstraints: 用于滚动布局,包含更复杂的信息

BoxConstraints源码:

// packages/flutter/lib/src/rendering/box.dart
class BoxConstraints extends Constraints {
  const BoxConstraints({
    this.minWidth = 0.0,
    this.maxWidth = double.infinity,
    this.minHeight = 0.0,
    this.maxHeight = double.infinity,
  });

  // 最小宽度
  final double minWidth;
  // 最大宽度
  final double maxWidth;
  // 最小高度
  final double minHeight;
  // 最大高度
  final double maxHeight;

  // 固定尺寸约束
  BoxConstraints.tight(Size size)
    : minWidth = size.width,
      maxWidth = size.width,
      minHeight = size.height,
      maxHeight = size.height;

  // 松散约束(只有最大尺寸限制)
  const BoxConstraints.loose(Size size)
    : minWidth = 0.0,
      maxWidth = size.width,
      minHeight = 0.0,
      maxHeight = size.height;

  // 扩展约束(尽可能大)
  const BoxConstraints.expand({
    double? width,
    double? height,
  }) : minWidth = width ?? double.infinity,
       maxWidth = width ?? double.infinity,
       minHeight = height ?? double.infinity,
       maxHeight = height ?? double.infinity;

  // 检查约束是否是有效的
  bool get isNormalized {
    return minWidth >= 0.0
        && minHeight >= 0.0
        && maxWidth >= minWidth
        && maxHeight >= minHeight;
  }

  // 应用约束到尺寸
  Size constrain(Size size) {
    Size result = Size(
      clampDouble(size.width, minWidth, maxWidth),
      clampDouble(size.height, minHeight, maxHeight),
    );
    return result;
  }
}

约束传递示例:

当你创建一个Row时,它的布局过程如下:

class Row extends Flex {
  Row({
    Key? key,
    MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
    CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
    List<Widget> children = const <Widget>[],
  }) : super(
    direction: Axis.horizontal,
    mainAxisAlignment: mainAxisAlignment,
    crossAxisAlignment: crossAxisAlignment,
    children: children,
  );
}

Row内部使用RenderFlex进行布局:

// packages/flutter/lib/src/rendering/flex.dart

void performLayout() {
  // ... 前面的代码 ...

  // 为子元素创建约束
  final BoxConstraints innerConstraints = BoxConstraints(
    maxWidth: direction == Axis.horizontal ? double.infinity : constraints.maxWidth,
    maxHeight: direction == Axis.horizontal ? constraints.maxHeight : double.infinity,
  );

  // 将约束传递给子元素
  RenderBox? child = firstChild;
  while (child != null) {
    child.layout(innerConstraints, parentUsesSize: true);
    // ... 其他代码 ...
    child = childParentData.nextSibling;
  }

  // ... 后面的代码 ...
}

约束的四种情况:

  1. 紧约束(Tight): minWidth=maxWidth, minHeight=maxHeight

    • 例如: BoxConstraints.tight(Size(100, 100))
    • 子元素必须是指定的尺寸
  2. 松约束(Loose): minWidth=0, minHeight=0

    • 例如: BoxConstraints.loose(Size(100, 100))
    • 子元素可以是任何不超过最大尺寸的尺寸
  3. 扩展约束(Expand): min=max=infinity

    • 例如: BoxConstraints.expand()
    • 子元素必须尽可能大
  4. 无边界约束(Unbounded): max=infinity

    • 例如: BoxConstraints(maxWidth: double.infinity, maxHeight: double.infinity)
    • 子元素可以是任意尺寸,通常在滚动视图中使用

3.2 布局算法详解

Flutter的布局过程是通过RenderObject的performLayout方法实现的。不同类型的RenderObject有不同的布局算法。

主要布局算法:

  1. Box布局(RenderBox): 处理矩形布局
  2. Sliver布局(RenderSliver): 处理滚动视图中的元素
  3. Flex布局(RenderFlex): 处理弹性布局(Row和Column)
  4. Stack布局(RenderStack): 处理叠加布局
  5. Wrap布局(RenderWrap): 处理换行布局

Flex布局算法:

Flex布局是Flutter中最常用的布局算法之一,用于Row和Column组件。其布局过程分为几个主要步骤:

// packages/flutter/lib/src/rendering/flex.dart

void performLayout() {
  // 第一步: 确定主轴和交叉轴的方向
  final BoxConstraints constraints = this.constraints;
  final bool horizontal = direction == Axis.horizontal;

  // 第二步: 计算子元素的约束
  final BoxConstraints innerConstraints;
  if (crossAxisAlignment == CrossAxisAlignment.stretch) {
    innerConstraints = BoxConstraints.tightFor(
      width: horizontal ? null : constraints.maxWidth,
      height: horizontal ? constraints.maxHeight : null,
    );
  } else {
    innerConstraints = BoxConstraints(
      maxWidth: horizontal ? double.infinity : constraints.maxWidth,
      maxHeight: horizontal ? constraints.maxHeight : double.infinity,
    );
  }

  // 第三步: 第一次遍历,确定非扩展子元素的大小和总伸缩比例
  double totalFlex = 0.0;
  double inflexibleSpace = 0.0;
  RenderBox? child = firstChild;
  while (child != null) {
    final FlexParentData childParentData = child.parentData! as FlexParentData;
    final int flex = childParentData.flex ?? 0;
    if (flex > 0) {
      totalFlex += flex;
    } else {
      child.layout(innerConstraints, parentUsesSize: true);
      inflexibleSpace += horizontal ? child.size.width : child.size.height;
    }
    child = childParentData.nextSibling;
  }

  // 第四步: 计算扩展子元素的大小
  final double availableSpace = math.max(
    0.0,
    (horizontal ? constraints.maxWidth : constraints.maxHeight) - inflexibleSpace,
  );

  double spacePerFlex = totalFlex > 0 ? availableSpace / totalFlex : 0.0;

  // 第五步: 第二次遍历,布局扩展子元素
  child = firstChild;
  while (child != null) {
    final FlexParentData childParentData = child.parentData! as FlexParentData;
    final int flex = childParentData.flex ?? 0;
    if (flex > 0) {
      final double childMainSize = spacePerFlex * flex;
      final BoxConstraints childConstraints = BoxConstraints(
        minWidth: horizontal ? childMainSize : innerConstraints.minWidth,
        maxWidth: horizontal ? childMainSize : innerConstraints.maxWidth,
        minHeight: horizontal ? innerConstraints.minHeight : childMainSize,
        maxHeight: horizontal ? innerConstraints.maxHeight : childMainSize,
      );
      child.layout(childConstraints, parentUsesSize: true);
    }
    child = childParentData.nextSibling;
  }

  // 第六步: 计算自身大小
  double mainSize = 0.0;
  double crossSize = 0.0;
  child = firstChild;
  while (child != null) {
    final FlexParentData childParentData = child.parentData! as FlexParentData;
    final double childMainSize = horizontal ? child.size.width : child.size.height;
    final double childCrossSize = horizontal ? child.size.height : child.size.width;
    mainSize += childMainSize;
    crossSize = math.max(crossSize, childCrossSize);
    child = childParentData.nextSibling;
  }

  // 第七步: 根据约束调整自身大小
  final double containerMainSize = horizontal
      ? constraints.constrain(Size(mainSize, 0.0)).width
      : constraints.constrain(Size(0.0, mainSize)).height;

  final double containerCrossSize = horizontal
      ? constraints.constrain(Size(0.0, crossSize)).height
      : constraints.constrain(Size(crossSize, 0.0)).width;

  size = horizontal
      ? Size(containerMainSize, containerCrossSize)
      : Size(containerCrossSize, containerMainSize);

  // 第八步: 根据主轴对齐方式计算子元素位置
  final double leadingSpace;
  final double betweenSpace;
  final int childCount = _childCount;

  switch (mainAxisAlignment) {
    case MainAxisAlignment.start:
      leadingSpace = 0.0;
      betweenSpace = 0.0;
      break;
    case MainAxisAlignment.end:
      leadingSpace = containerMainSize - mainSize;
      betweenSpace = 0.0;
      break;
    case MainAxisAlignment.center:
      leadingSpace = (containerMainSize - mainSize) / 2.0;
      betweenSpace = 0.0;
      break;
    case MainAxisAlignment.spaceBetween:
      leadingSpace = 0.0;
      betweenSpace = childCount > 1 ? (containerMainSize - mainSize) / (childCount - 1) : 0.0;
      break;
    case MainAxisAlignment.spaceAround:
      betweenSpace = childCount > 0 ? (containerMainSize - mainSize) / childCount : 0.0;
      leadingSpace = betweenSpace / 2.0;
      break;
    case MainAxisAlignment.spaceEvenly:
      betweenSpace = childCount > 0 ? (containerMainSize - mainSize) / (childCount + 1) : 0.0;
      leadingSpace = betweenSpace;
      break;
  }

  // 第九步: 设置子元素的位置
  double childMainPosition = leadingSpace;
  child = firstChild;
  while (child != null) {
    final FlexParentData childParentData = child.parentData! as FlexParentData;
    final double childMainSize = horizontal ? child.size.width : child.size.height;
    final double childCrossSize = horizontal ? child.size.height : child.size.width;
    double childCrossPosition;

    // 根据交叉轴对齐方式计算子元素位置
    switch (crossAxisAlignment) {
      case CrossAxisAlignment.start:
        childCrossPosition = 0.0;
        break;
      case CrossAxisAlignment.end:
        childCrossPosition = containerCrossSize - childCrossSize;
        break;
      case CrossAxisAlignment.center:
        childCrossPosition = (containerCrossSize - childCrossSize) / 2.0;
        break;
      case CrossAxisAlignment.stretch:
        childCrossPosition = 0.0;
        break;
      case CrossAxisAlignment.baseline:
        // Baseline对齐需要特殊处理
        childCrossPosition = 0.0;
        break;
    }

    // 设置子元素位置
    if (horizontal) {
      childParentData.offset = Offset(childMainPosition, childCrossPosition);
    } else {
      childParentData.offset = Offset(childCrossPosition, childMainPosition);
    }

    childMainPosition += childMainSize + betweenSpace;
    child = childParentData.nextSibling;
  }
}

Stack布局算法:

Stack布局允许子元素相互重叠,其布局算法如下:

// packages/flutter/lib/src/rendering/stack.dart

void performLayout() {
  final BoxConstraints constraints = this.constraints;
  _hasVisualOverflow = false;

  // 计算Stack的尺寸
  if (children.isEmpty) {
    size = constraints.biggest;
    return;
  }

  double width = 0.0;
  double height = 0.0;

  // 第一步: 布局非定位子元素,确定最小尺寸
  RenderBox? child = firstChild;
  while (child != null) {
    final StackParentData childParentData = child.parentData! as StackParentData;

    if (!childParentData.isPositioned) {
      child.layout(constraints.loosen(), parentUsesSize: true);
      width = math.max(width, child.size.width);
      height = math.max(height, child.size.height);
    }

    child = childParentData.nextSibling;
  }

  // 第二步: 确定Stack的尺寸
  size = constraints.constrain(Size(width, height));

  // 第三步: 布局定位子元素
  child = firstChild;
  while (child != null) {
    final StackParentData childParentData = child.parentData! as StackParentData;

    if (childParentData.isPositioned) {
      final BoxConstraints childConstraints = BoxConstraints();

      // 根据定位参数计算约束
      if (childParentData.left != null && childParentData.right != null) {
        childConstraints.maxWidth = size.width - childParentData.left! - childParentData.right!;
      } else if (childParentData.width != null) {
        childConstraints.maxWidth = childParentData.width;
      }

      if (childParentData.top != null && childParentData.bottom != null) {
        childConstraints.maxHeight = size.height - childParentData.top! - childParentData.bottom!;
      } else if (childParentData.height != null) {
        childConstraints.maxHeight = childParentData.height;
      }

      child.layout(childConstraints, parentUsesSize: true);

      // 计算子元素位置
      double x = 0.0;
      if (childParentData.left != null) {
        x = childParentData.left!;
      } else if (childParentData.right != null) {
        x = size.width - childParentData.right! - child.size.width;
      }

      double y = 0.0;
      if (childParentData.top != null) {
        y = childParentData.top!;
      } else if (childParentData.bottom != null) {
        y = size.height - childParentData.bottom! - child.size.height;
      }

      childParentData.offset = Offset(x, y);
    } else {
      // 非定位子元素位置
      final BoxConstraints childConstraints;
      if (alignment == null) {
        childConstraints = BoxConstraints.loose(size);
      } else {
        childConstraints = BoxConstraints.tight(size);
      }

      child.layout(childConstraints, parentUsesSize: true);

      // 根据alignment计算位置
      childParentData.offset = alignment.resolve(textDirection).alongOffset(
        size - child.size as Offset,
      );
    }

    child = childParentData.nextSibling;
  }
}

3.3 自定义布局示例

Flutter允许创建自定义布局,通过扩展RenderObject或使用CustomMultiChildLayout等方式。

自定义RenderObject:

创建自定义RenderObject需要重写performLayoutpaint方法:

class RenderWaterfall extends RenderBox
    with ContainerRenderObjectMixin<RenderBox, WaterfallParentData>,
         RenderBoxContainerDefaultsMixin<RenderBox, WaterfallParentData> {
  RenderWaterfall({
    required int columnCount,
    required double columnSpacing,
    required double rowSpacing,
  }) : _columnCount = columnCount,
       _columnSpacing = columnSpacing,
       _rowSpacing = rowSpacing;

  int _columnCount;
  double _columnSpacing;
  double _rowSpacing;

  // 设置子元素的parentData
  
  void setupParentData(RenderBox child) {
    if (child.parentData is! WaterfallParentData) {
      child.parentData = WaterfallParentData();
    }
  }

  // 自定义布局算法
  
  void performLayout() {
    if (childCount == 0) {
      size = constraints.constrain(Size.zero);
      return;
    }

    final BoxConstraints childConstraints = BoxConstraints(
      maxWidth: (constraints.maxWidth - (_columnCount - 1) * _columnSpacing) / _columnCount,
    );

    // 每列的高度
    final List<double> columnHeights = List<double>.filled(_columnCount, 0.0);

    // 第一步: 布局所有子元素
    RenderBox? child = firstChild;
    while (child != null) {
      final WaterfallParentData parentData = child.parentData! as WaterfallParentData;

      // 布局子元素
      child.layout(childConstraints, parentUsesSize: true);

      // 找到高度最小的列
      int minColumnIndex = 0;
      double minColumnHeight = columnHeights[0];
      for (int i = 1; i < _columnCount; i++) {
        if (columnHeights[i] < minColumnHeight) {
          minColumnIndex = i;
          minColumnHeight = columnHeights[i];
        }
      }

      // 计算子元素位置
      final double x = minColumnIndex * (childConstraints.maxWidth + _columnSpacing);
      final double y = columnHeights[minColumnIndex];

      // 设置子元素位置
      parentData.offset = Offset(x, y);

      // 更新列高度
      columnHeights[minColumnIndex] += child.size.height + _rowSpacing;

      child = parentData.nextSibling;
    }

    // 第二步: 计算自身大小
    final double height = columnHeights.reduce(math.max) - _rowSpacing;
    size = constraints.constrain(Size(constraints.maxWidth, height));
  }

  // 绘制
  
  void paint(PaintingContext context, Offset offset) {
    defaultPaint(context, offset);
  }

  // 命中测试
  
  bool hitTestChildren(BoxHitTestResult result, { required Offset position }) {
    return defaultHitTestChildren(result, position: position);
  }
}

// 自定义ParentData
class WaterfallParentData extends ContainerBoxParentData<RenderBox> {}

使用CustomMultiChildLayout:

Flutter也提供了更简单的方式来创建自定义布局,通过CustomMultiChildLayout:

class MyCustomLayout extends StatelessWidget {
  final List<Widget> children;

  MyCustomLayout({required this.children});

  
  Widget build(BuildContext context) {
    return CustomMultiChildLayout(
      delegate: MyLayoutDelegate(),
      children: List.generate(
        children.length,
        (index) => LayoutId(
          id: 'child$index',
          child: children[index],
        ),
      ),
    );
  }
}

class MyLayoutDelegate extends MultiChildLayoutDelegate {
  
  void performLayout(Size size) {
    // 获取子元素的数量
    int count = 0;
    while (hasChild('child$count')) {
      count++;
    }

    // 布局逻辑
    for (int i = 0; i < count; i++) {
      final String id = 'child$i';

      // 获取子元素的尺寸
      final Size childSize = layoutChild(
        id,
        BoxConstraints.loose(size),
      );

      // 计算位置
      final double x = i * childSize.width;
      final double y = (i % 2) * childSize.height;

      // 放置子元素
      positionChild(id, Offset(x, y));
    }
  }

  
  bool shouldRelayout(covariant MultiChildLayoutDelegate oldDelegate) {
    return true;
  }
}

布局约束调试:

Flutter提供了调试布局约束的工具,当遇到布局问题时非常有用:

import 'package:flutter/rendering.dart';

void main() {
  // 打开布局约束调试
  debugPrintMarkNeedsLayoutStacks = true;

  runApp(MyApp());
}

使用LayoutBuilder查看约束:

LayoutBuilder(
  builder: (BuildContext context, BoxConstraints constraints) {
    print('约束: $constraints');
    return Container(
      width: constraints.maxWidth,
      height: constraints.maxHeight,
      color: Colors.blue,
    );
  },
)

4. 渲染系统实现细节

4.1 图层树(Layer Tree)构建

Flutter的渲染管线最终会创建一个图层树(Layer Tree),这是连接渲染逻辑和GPU绘制的桥梁。图层树由不同类型的Layer组成,每种Layer处理不同的渲染任务。

Layer类的层次结构:

Layer (基类)
├── ContainerLayer (可包含子Layer)
│   ├── OffsetLayer (应用偏移)
│   ├── ClipRectLayer (矩形裁剪)
│   ├── ClipRRectLayer (圆角矩形裁剪)
│   ├── ClipPathLayer (路径裁剪)
│   ├── TransformLayer (变换)
│   └── ShaderMaskLayer (着色器蒙版)
├── PictureLayer (包含绘制命令)
├── TextureLayer (纹理)
├── ColorFilterLayer (颜色滤镜)
└── OpacityLayer (透明度)

Layer基类源码:

// packages/flutter/lib/src/rendering/layer.dart
class Layer extends AbstractNode with DiagnosticableTreeMixin {
  // 包围盒
  Rect? _layerBounds;

  // 是否需要重新计算包围盒
  bool _needsAddToScene = true;

  // 添加自身到场景
  void addToScene(ui.SceneBuilder builder, [ Offset layerOffset = Offset.zero ]);

  // 更新层
  void updateSubtreeNeedsAddToScene() {
    _needsAddToScene = true;
  }

  // 预绘制
  void preroll(PrerollContext context, Matrix4 matrix);
}

ContainerLayer源码:

// packages/flutter/lib/src/rendering/layer.dart
class ContainerLayer extends Layer {
  // 子层列表
  List<Layer>? _children;

  // 添加子层
  void append(Layer child) {
    child._remove();
    child._parent = this;
    _children ??= <Layer>[];
    _children!.add(child);
  }

  // 添加到场景
  
  void addToScene(ui.SceneBuilder builder, [ Offset layerOffset = Offset.zero ]) {
    // 添加所有子层到场景
    if (_children != null) {
      for (final Layer child in _children!) {
        child.addToScene(builder, layerOffset);
      }
    }
  }
}

PictureLayer源码:

// packages/flutter/lib/src/rendering/layer.dart
class PictureLayer extends Layer {
  PictureLayer(Rect canvasBounds)
   : _canvasBounds = canvasBounds;

  // 图片记录器
  ui.PictureRecorder? _recorder;
  // 图片
  ui.Picture? _picture;
  // 绘制边界
  Rect _canvasBounds;

  // 开始记录绘制命令
  ui.Canvas beginRecording() {
    _recorder = ui.PictureRecorder();
    return ui.Canvas(_recorder!);
  }

  // 结束记录
  ui.Picture endRecording() {
    _picture = _recorder!.endRecording();
    _recorder = null;
    return _picture!;
  }

  // 添加到场景
  
  void addToScene(ui.SceneBuilder builder, [ Offset layerOffset = Offset.zero ]) {
    if (_picture == null)
      return;

    // 将图片添加到场景
    builder.addPicture(layerOffset, _picture!);
  }
}

图层树构建过程:

图层树的构建从RenderView.compositeFrame()开始:

// packages/flutter/lib/src/rendering/view.dart
void compositeFrame() {
  // 创建场景构建器
  final ui.SceneBuilder builder = ui.SceneBuilder();

  // 创建图层树
  final ui.Scene scene = layer!.buildScene(builder);

  // 将场景提交到引擎
  window.render(scene);

  // 释放资源
  scene.dispose();
}

Layer.buildScene()中,会遍历整个图层树:

// packages/flutter/lib/src/rendering/layer.dart
ui.Scene buildScene(ui.SceneBuilder builder) {
  // 更新图层树
  updateSubtreeNeedsAddToScene();

  // 添加自身到场景
  addToScene(builder);

  // 构建场景
  return builder.build();
}

实际示例: 构建图层树:

以一个带有阴影的容器为例,其图层树构建过程:

// Widget代码
Container(
  decoration: BoxDecoration(
    color: Colors.white,
    boxShadow: [
      BoxShadow(
        color: Colors.black.withOpacity(0.1),
        blurRadius: 5,
        offset: Offset(0, 3),
      ),
    ],
  ),
  child: Text('Hello'),
)

对应的渲染过程:

  1. 创建一个PictureLayer绘制阴影
  2. 创建一个PictureLayer绘制容器背景
  3. 创建一个PictureLayer绘制文本
  4. 将这些PictureLayer添加到ContainerLayer中

4.2 绘制过程与合成

Flutter的绘制过程从RenderObject的paint方法开始,经过PaintingContext转换为图层树,最终由引擎进行合成。

RenderObject绘制:

RenderObject的paint方法负责将自身绘制到PaintingContext:

// 以RenderParagraph为例(Text的渲染对象)
// packages/flutter/lib/src/rendering/paragraph.dart

void paint(PaintingContext context, Offset offset) {
  if (_needsClipping) {
    // 如果需要裁剪,创建一个裁剪层
    context.pushClipRect(needsCompositing, offset, Offset.zero & size, _paint);
  } else {
    // 直接绘制文本
    _paint(context, offset);
  }
}

void _paint(PaintingContext context, Offset offset) {
  // 获取画布
  final Canvas canvas = context.canvas;

  // 设置文本绘制位置
  _textPainter.paint(canvas, offset);

  // 如果有选择区域,绘制选择区域
  if (_selectionRects != null) {
    for (final TextBox textBox in _selectionRects!) {
      canvas.drawRect(
        textBox.toRect().shift(offset),
        _selectionPaint,
      );
    }
  }
}

PaintingContext源码:

PaintingContext是RenderObject和Canvas之间的桥梁,它管理绘制操作和图层创建:

// packages/flutter/lib/src/rendering/object.dart
class PaintingContext extends ClipContext {
  // 创建绘制上下文
  PaintingContext(this._containerLayer, this.estimatedBounds);

  // 容器层
  final ContainerLayer _containerLayer;

  // 绘制区域
  final Rect estimatedBounds;

  // 画布
  Canvas? _canvas;

  // 当前记录器
  PictureLayer? _recorder;

  // 获取画布
  Canvas get canvas {
    if (_canvas == null) {
      _startRecording();
    }
    return _canvas!;
  }

  // 开始记录绘制命令
  void _startRecording() {
    _recorder = PictureLayer(estimatedBounds);
    _canvas = _recorder!.beginRecording();
    _containerLayer.append(_recorder!);
  }

  // 停止记录
  void stopRecordingIfNeeded() {
    if (_recorder != null) {
      _recorder!.endRecording();
      _recorder = null;
      _canvas = null;
    }
  }

  // 创建裁剪层
  void pushClipRect(bool needsCompositing, Offset offset, Rect clipRect, PaintingContextCallback painter) {
    if (needsCompositing) {
      // 如果需要合成,创建新的裁剪层
      final ClipRectLayer clipLayer = ClipRectLayer(clipRect: clipRect.shift(offset));
      pushLayer(clipLayer, painter, offset);
    } else {
      // 否则直接裁剪画布
      canvas.save();
      canvas.clipRect(clipRect.shift(offset));
      painter(this, offset);
      canvas.restore();
    }
  }

  // 创建变换层
  void pushTransform(bool needsCompositing, Offset offset, Matrix4 transform, PaintingContextCallback painter) {
    if (needsCompositing) {
      // 如果需要合成,创建新的变换层
      final Matrix4 effectiveTransform = Matrix4.translationValues(offset.dx, offset.dy, 0.0)
        ..multiply(transform)
        ..translate(-offset.dx, -offset.dy);
      final TransformLayer transformLayer = TransformLayer(transform: effectiveTransform);
      pushLayer(transformLayer, painter, offset);
    } else {
      // 否则直接变换画布
      canvas.save();
      canvas.translate(offset.dx, offset.dy);
      canvas.transform(transform.storage);
      canvas.translate(-offset.dx, -offset.dy);
      painter(this, offset);
      canvas.restore();
    }
  }

  // 创建新层
  void pushLayer(ContainerLayer childLayer, PaintingContextCallback painter, Offset offset) {
    // 停止当前记录
    stopRecordingIfNeeded();

    // 将子层添加到容器层
    _containerLayer.append(childLayer);

    // 创建新的绘制上下文
    final PaintingContext childContext = PaintingContext(childLayer, estimatedBounds);

    // 调用绘制回调
    painter(childContext, offset);

    // 停止子上下文的记录
    childContext.stopRecordingIfNeeded();
  }
}

合成过程:

合成过程是将图层树转换为GPU可以渲染的命令序列。这个过程在Flutter引擎中完成:

// engine/src/flutter/flow/compositor_context.cc
void CompositorContext::BeginFrame(fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger) {
  // 初始化帧状态
  if (raster_thread_merger) {
    raster_thread_merger_ = raster_thread_merger;
  }

  // 记录帧开始时间
  const auto now = fml::TimePoint::Now();
  const auto frame_time = time_converter_.ToFrameTime(now);
  frame_times_.push_back(frame_time);
}

void CompositorContext::EndFrame(ScopedFrame& frame, bool end_raster_thread_merger) {
  // 释放帧资源
  if (raster_thread_merger_ && end_raster_thread_merger) {
    raster_thread_merger_->EndFrame();
    raster_thread_merger_ = nullptr;
  }

  // 更新统计信息
  const auto now = fml::TimePoint::Now();
  while (!frame_times_.empty()) {
    const auto& oldest_frame_time = frame_times_.front();
    if (now - oldest_frame_time < kFrameTimeThreshold) {
      break;
    }
    frame_times_.pop_front();
  }
}

std::unique_ptr<ScopedFrame> CompositorContext::AcquireFrame(
    GrDirectContext* gr_context,
    SkCanvas* canvas,
    ExternalViewEmbedder* view_embedder,
    const SkMatrix& root_surface_transformation,
    bool instrumentation_enabled) {
  // 创建一个新帧
  return std::make_unique<ScopedFrame>(*this, gr_context, canvas, view_embedder,
                                      root_surface_transformation,
                                      instrumentation_enabled);
}

渲染管线优化:

Flutter引擎包含多种优化技术,提高渲染性能:

  1. 图层合并: 尽可能减少图层数量
  2. 渲染缓存: 缓存不变的渲染结果
  3. 裁剪优化: 只渲染可见区域
  4. 纹理压缩: 减少GPU内存占用

渲染缓存源码:

// packages/flutter/lib/src/rendering/proxy_box.dart
class RenderRepaintBoundary extends RenderProxyBox {
  
  bool get isRepaintBoundary => true;

  
  void paint(PaintingContext context, Offset offset) {
    // 当作为重绘边界时,会创建新的图层
    context.pushLayer(OffsetLayer(), super.paint, offset);
  }
}

在底层,这会触发渲染缓存机制:

// engine/src/flutter/flow/raster_cache.cc
bool RasterCache::Prepare(PrerollContext* context,
                         Layer* layer,
                         const SkMatrix& matrix) {
  // 检查是否应该缓存
  if (!IsCacheable(layer, matrix)) {
    return false;
  }

  // 创建缓存条目
  auto entry = Entry{
    .layer = layer,
    .matrix = matrix,
  };

  // 检查是否已经在缓存中
  auto it = cache_.find(entry);
  if (it != cache_.end()) {
    // 更新命中计数
    it->second.access_count++;

    // 检查是否需要重新渲染
    if (it->second.access_count >= kMinimumAccessCount) {
      it->second.image = RasterizeSurface(context, layer, matrix);
    }
  } else {
    // 添加到缓存
    cache_[entry] = {
      .access_count = 1,
      .image = nullptr,
    };
  }

  return true;
}

sk_sp<SkImage> RasterCache::RasterizeSurface(PrerollContext* context,
                                           Layer* layer,
                                           const SkMatrix& matrix) {
  // 创建离屏渲染目标
  SkRect bounds = layer->paint_bounds();
  SkImageInfo image_info = SkImageInfo::MakeN32Premul(
      bounds.width(), bounds.height());

  // 创建Surface
  auto surface = SkSurface::MakeRenderTarget(
      context->gr_context, SkBudgeted::kYes, image_info);

  // 获取画布
  auto canvas = surface->getCanvas();

  // 设置变换
  canvas->translate(-bounds.left, -bounds.top);
  canvas->concat(matrix);

  // 绘制图层
  PaintContext paint_context = {
      .canvas = canvas,
      .gr_context = context->gr_context,
      .view_embedder = context->view_embedder,
      .raster_cache = this,
  };
  layer->Paint(&paint_context);

  // 生成图像
  return surface->makeImageSnapshot();
}

4.3 光栅化与GPU渲染

Flutter的渲染管线最后阶段是光栅化和GPU渲染,这是将图层树转换为像素的过程。

光栅化过程:

光栅化是将矢量图形转换为像素点阵的过程。在Flutter中,这一过程由Skia引擎负责:

// engine/src/flutter/flow/layers/layer_tree.cc
void LayerTree::Preroll(CompositorContext::ScopedFrame& frame) {
  // 预处理阶段,计算各层的包围盒
  frame.context().beginFrame(nullptr);

  // 准备上下文
  PrerollContext context = {
      frame.gr_context(),                   // GrContext
      frame.view_embedder(),                // ExternalViewEmbedder
      &frame.context().raster_cache(),      // RasterCache
      false,                                // subtree_can_inherit_opacity
  };

  // 预处理根层
  root_layer_->Preroll(&context, frame.root_surface_transformation());
}

void LayerTree::Paint(CompositorContext::ScopedFrame& frame) {
  // 光栅化阶段,将图层树绘制到画布
  if (root_layer_->needs_painting()) {
    // 准备上下文
    PaintContext context = {
        frame.canvas(),                     // canvas
        frame.gr_context(),                 // gr_context
        frame.view_embedder(),              // view_embedder
        &frame.context().raster_cache(),    // raster_cache
    };

    // 绘制根层
    root_layer_->Paint(&context);
  }
}

在Skia内部,光栅化过程涉及以下步骤:

  1. 几何处理: 将矢量描述转换为三角形网格
  2. 着色: 计算每个像素的颜色值
  3. 纹理映射: 将纹理应用到几何图形上
  4. 混合: 处理透明度和混合模式

GPU渲染:

光栅化后的数据最终会传递给GPU进行渲染。Flutter使用Skia的GPU后端(GrContext)来与GPU交互:

// engine/src/flutter/shell/common/rasterizer.cc
void Rasterizer::Draw(std::unique_ptr<FramePipeline::Iterator> pipeline) {
  // 处理所有待渲染的帧
  while (pipeline->HasNextFrame()) {
    // 获取下一帧
    auto frame = pipeline->GetNextFrame();

    // 如果帧无效,跳过
    if (frame.IsEmpty()) {
      continue;
    }

    // 绘制当前帧
    DrawToSurface(frame);

    // 通知帧已完成
    pipeline->UnregisterFrame();
  }
}

void Rasterizer::DrawToSurface(FramePipeline::FrameResult& frame) {
  // 准备Surface
  auto surface = surface_producer_->ProduceSurface(frame.GetFrameSize());

  if (!surface) {
    return;
  }

  // 获取画布
  auto canvas = surface->getCanvas();

  // 获取GrContext
  auto gr_context = surface_producer_->GetContext();

  // 创建合成上下文
  CompositorContext::ScopedFrame compositor_frame =
      compositor_context_.AcquireFrame(gr_context, canvas, nullptr,
                                     surface_producer_->GetRootTransformation());

  // 预处理图层树
  frame.GetLayerTree().Preroll(compositor_frame);

  // 绘制图层树
  frame.GetLayerTree().Paint(compositor_frame);

  // 提交Surface
  surface_producer_->PresentSurface(std::move(surface));
}

渲染管线优化:

Flutter引擎包含多种优化技术,提高渲染性能:

  1. 图层合并: 尽可能减少图层数量
  2. 渲染缓存: 缓存不变的渲染结果
  3. 裁剪优化: 只渲染可见区域
  4. 纹理压缩: 减少GPU内存占用

渲染缓存源码:

// packages/flutter/lib/src/rendering/proxy_box.dart
class RenderRepaintBoundary extends RenderProxyBox {
  
  bool get isRepaintBoundary => true;

  
  void paint(PaintingContext context, Offset offset) {
    // 当作为重绘边界时,会创建新的图层
    context.pushLayer(OffsetLayer(), super.paint, offset);
  }
}

在底层,这会触发渲染缓存机制:

// engine/src/flutter/flow/raster_cache.cc
bool RasterCache::Prepare(PrerollContext* context,
                         Layer* layer,
                         const SkMatrix& matrix) {
  // 检查是否应该缓存
  if (!IsCacheable(layer, matrix)) {
    return false;
  }

  // 创建缓存条目
  auto entry = Entry{
    .layer = layer,
    .matrix = matrix,
  };

  // 检查是否已经在缓存中
  auto it = cache_.find(entry);
  if (it != cache_.end()) {
    // 更新命中计数
    it->second.access_count++;

    // 检查是否需要重新渲染
    if (it->second.access_count >= kMinimumAccessCount) {
      it->second.image = RasterizeSurface(context, layer, matrix);
    }
  } else {
    // 添加到缓存
    cache_[entry] = {
      .access_count = 1,
      .image = nullptr,
    };
  }

  return true;
}

sk_sp<SkImage> RasterCache::RasterizeSurface(PrerollContext* context,
                                           Layer* layer,
                                           const SkMatrix& matrix) {
  // 创建离屏渲染目标
  SkRect bounds = layer->paint_bounds();
  SkImageInfo image_info = SkImageInfo::MakeN32Premul(
      bounds.width(), bounds.height());

  // 创建Surface
  auto surface = SkSurface::MakeRenderTarget(
      context->gr_context, SkBudgeted::kYes, image_info);

  // 获取画布
  auto canvas = surface->getCanvas();

  // 设置变换
  canvas->translate(-bounds.left, -bounds.top);
  canvas->concat(matrix);

  // 绘制图层
  PaintContext paint_context = {
      .canvas = canvas,
      .gr_context = context->gr_context,
      .view_embedder = context->view_embedder,
      .raster_cache = this,
  };
  layer->Paint(&paint_context);

  // 生成图像
  return surface->makeImageSnapshot();
}

5. 状态管理与更新机制

Flutter的状态管理是其响应式UI框架的核心。本节将深入分析Flutter状态更新的完整链路,BuildOwner的作用,以及setState的内部实现。

5.1 状态更新完整链路

Flutter的状态更新涉及一系列精心设计的步骤,从setState调用到屏幕刷新的完整链路如下:

状态更新链路图:

setState() → markNeedsBuild() → scheduleBuildFor() →
scheduleFrame() → [VSync信号] → handleBeginFrame() → handleDrawFrame() →
drawFrame() → buildScope() → Element.rebuild() → build() →
flushLayout() → flushPaint() → compositeFrame() → render()

1. 状态变更触发:

当调用setState时,会触发状态更新的起点:

// packages/flutter/lib/src/widgets/framework.dart

void setState(VoidCallback fn) {
  // 断言不在build方法中调用setState
  assert(_debugLifecycleState != _StateLifecycle.build);
  // 断言Widget已挂载
  assert(_debugLifecycleState != _StateLifecycle.defunct);

  // 执行状态更新函数
  fn();

  // 标记Element需要重建
  _element!.markNeedsBuild();
}

2. 标记Element需要重建:

markNeedsBuild方法将Element标记为dirty并安排重建:

// packages/flutter/lib/src/widgets/framework.dart
void markNeedsBuild() {
  // 如果已经被标记为dirty,直接返回
  if (_dirty)
    return;

  // 检查Element是否还活跃
  if (!_active)
    return;

  // 标记为dirty
  _dirty = true;

  // 将Element添加到BuildOwner的待重建列表
  owner!.scheduleBuildFor(this);
}

3. BuildOwner调度重建:

scheduleBuildFor将Element添加到脏元素列表:

// packages/flutter/lib/src/widgets/framework.dart
void scheduleBuildFor(Element element) {
  // 只有处于clean状态的Element才需要加入重建队列
  if (!element._dirty) {
    _dirtyElements.add(element);
    element._dirty = true;
  }

  // 请求新的一帧
  scheduleFrame();
}

4. 请求新的一帧:

scheduleFrame通知Flutter引擎在下一个VSync信号到来时绘制新帧:

// packages/flutter/lib/src/scheduler/binding.dart
void scheduleFrame() {
  if (_hasScheduledFrame || !_framesEnabled)
    return;

  // 向引擎请求新帧
  ui.PlatformDispatcher.instance.scheduleFrame();
  _hasScheduledFrame = true;
}

5. 处理帧回调:

当VSync信号到来时,Flutter引擎会调用handleBeginFramehandleDrawFrame:

// packages/flutter/lib/src/scheduler/binding.dart
('vm:notify-debugger-on-exception')
void handleBeginFrame(Duration? rawTimeStamp) {
  // 记录帧开始时间
  Timeline.startSync('Frame', arguments: timelineWhitelistArguments);

  // 处理动画和其他瞬态回调
  _schedulerPhase = SchedulerPhase.transientCallbacks;
  final Map<int, _FrameCallbackEntry> callbacks = _transientCallbacks;
  _transientCallbacks = <int, _FrameCallbackEntry>{};
  callbacks.forEach((int id, _FrameCallbackEntry callbackEntry) {
    if (!_removedIds.contains(id))
      _invokeFrameCallback(callbackEntry.callback, _currentFrameTimeStamp!, callbackEntry.debugStack);
  });

  // 进入微任务阶段
  _schedulerPhase = SchedulerPhase.midFrameMicrotasks;
}

('vm:notify-debugger-on-exception')
void handleDrawFrame() {
  // 处理持久性回调(例如构建和布局)
  _schedulerPhase = SchedulerPhase.persistentCallbacks;
  for (final FrameCallback callback in _persistentCallbacks)
    _invokeFrameCallback(callback, _currentFrameTimeStamp!, null);

  // 处理帧结束回调
  _schedulerPhase = SchedulerPhase.postFrameCallbacks;
  final List<FrameCallback> localPostFrameCallbacks =
      List<FrameCallback>.from(_postFrameCallbacks);
  _postFrameCallbacks.clear();
  for (final FrameCallback callback in localPostFrameCallbacks)
    _invokeFrameCallback(callback, _currentFrameTimeStamp!, null);

  // 回到空闲状态
  _schedulerPhase = SchedulerPhase.idle;
}

6. Widget绑定绘制帧:

在持久性回调阶段,WidgetsBinding.drawFrame被调用:

// packages/flutter/lib/src/widgets/binding.dart

void drawFrame() {
  try {
    // 首先重建所有标记为dirty的元素
    if (renderViewElement != null)
      buildOwner!.buildScope(renderViewElement!);

    // 然后进行布局和绘制
    super.drawFrame();

    // 最后完成树构建
    buildOwner!.finalizeTree();
  } finally {
    // ...
  }
}

7. BuildOwner构建作用域:

buildScope方法会重建所有dirty元素:

// packages/flutter/lib/src/widgets/framework.dart
void buildScope(Element context, [VoidCallback? callback]) {
  if (callback != null) {
    Timeline.startSync('Build', arguments: timelineWhitelistArguments);
    try {
      callback();
    } finally {
      Timeline.finishSync();
    }
  }

  // 按照深度排序脏元素,从根到叶
  _dirtyElements.sort(Element._sort);

  // 重建所有脏元素
  int dirtyCount = _dirtyElements.length;
  int index = 0;
  while (index < dirtyCount) {
    final Element element = _dirtyElements[index];
    if (element._dirty && element.active) {
      element.rebuild();
    }
    index += 1;
  }

  // 清空脏元素列表
  _dirtyElements.clear();
}

8. Element重建:

每个dirty元素都会调用rebuild方法进行重建:

// packages/flutter/lib/src/widgets/framework.dart
void rebuild() {
  if (!_active || !_dirty)
    return;

  // 执行重建
  performRebuild();
}

9. StatefulElement重建:

对于StatefulElement,performRebuild会调用State的build方法:

// packages/flutter/lib/src/widgets/framework.dart

void performRebuild() {
  // 调用state.build获取新的Widget
  final Widget built = build();

  // 更新子Element树
  _child = updateChild(_child, built, slot);

  // 标记为不再dirty
  _dirty = false;
}


Widget build() => state.build(this);

10. 渲染阶段:

完成Widget树重建后,进行渲染阶段:

// packages/flutter/lib/src/rendering/binding.dart

void drawFrame() {
  // 执行布局
  pipelineOwner.flushLayout();

  // 确定合成位
  pipelineOwner.flushCompositingBits();

  // 执行绘制
  pipelineOwner.flushPaint();

  // 合成帧并发送到GPU
  renderView.compositeFrame();
}

11. 布局与绘制:

flushLayoutflushPaint中,所有标记为需要布局或绘制的RenderObject会被处理:

// packages/flutter/lib/src/rendering/object.dart
void flushLayout() {
  // 处理所有需要布局的RenderObject
  while (_nodesNeedingLayout.isNotEmpty) {
    final List<RenderObject> dirtyNodes = _nodesNeedingLayout;
    _nodesNeedingLayout = <RenderObject>[];

    // 按照深度排序,从根到叶
    dirtyNodes.sort((RenderObject a, RenderObject b) => a.depth - b.depth);

    // 对每个节点执行布局
    for (final RenderObject node in dirtyNodes) {
      if (node._needsLayout && node.owner == this)
        node._layoutWithoutResize();
    }
  }
}

void flushPaint() {
  // 处理所有需要绘制的RenderObject
  final List<RenderObject> dirtyNodes = _nodesNeedingPaint;
  _nodesNeedingPaint = <RenderObject>[];

  // 按照深度排序,从叶到根
  dirtyNodes.sort((RenderObject a, RenderObject b) => b.depth - a.depth);

  // 对每个节点执行绘制
  for (final RenderObject node in dirtyNodes) {
    if (node._needsPaint && node.owner == this) {
      if (node._layer == null || node._layer!.attached)
        PaintingContext.repaintCompositedChild(node);
      else
        node._skippedPaintingOnLayer();
    }
  }
}

12. 合成与渲染:

最后,compositeFrame将绘制结果合成为一个场景并发送到GPU:

// packages/flutter/lib/src/rendering/view.dart
void compositeFrame() {
  // 创建场景构建器
  final ui.SceneBuilder builder = ui.SceneBuilder();

  // 构建场景
  final ui.Scene scene = layer!.buildScene(builder);

  // 发送场景到GPU
  ui.window.render(scene);

  // 释放场景资源
  scene.dispose();
}

整个状态更新链路展示了Flutter从状态变化到屏幕更新的完整流程,体现了其响应式UI框架的精妙设计。

5.2 BuildOwner与更新调度

BuildOwner是Flutter状态管理的核心协调器,负责管理Element的构建和更新。

BuildOwner的核心职责:

  1. 维护和调度脏Element的重建
  2. 管理焦点树
  3. 处理语义更新
  4. 协调整体UI更新流程

BuildOwner的源码结构:

// packages/flutter/lib/src/widgets/framework.dart
class BuildOwner {
  BuildOwner({this.onBuildScheduled, this.focusManager});

  // 构建调度回调
  final VoidCallback? onBuildScheduled;

  // 焦点管理器
  final FocusManager? focusManager;

  // 脏元素列表
  final List<Element> _dirtyElements = <Element>[];

  // 是否禁用构建
  bool _scheduledBuildPhase = false;

  // 标记元素需要重建
  void scheduleBuildFor(Element element) {
    if (element._dirty)
      return;
    _dirtyElements.add(element);
    element._dirty = true;

    // 调度构建
    if (onBuildScheduled != null && !_scheduledBuildPhase) {
      _scheduledBuildPhase = true;
      onBuildScheduled!();
    }
  }

  // 执行构建
  void buildScope(Element context, [VoidCallback? callback]) {
    // 执行传入的回调
    if (callback != null) {
      callback();
    }

    // 排序脏元素
    _dirtyElements.sort(Element._sort);

    // 重建所有脏元素
    int index = 0;
    while (index < _dirtyElements.length) {
      final Element element = _dirtyElements[index];
      if (element._dirty && element.active) {
        element.rebuild();
      }
      index += 1;
    }

    // 清空脏元素列表
    _dirtyElements.clear();
    _scheduledBuildPhase = false;
  }

  // 完成树构建
  void finalizeTree() {
    // 处理未发送的状态变更
    for (final Element element in _dirtyElements) {
      if (element.dirty && element.active) {
        element.rebuild();
      }
    }
    _dirtyElements.clear();

    // 更新焦点
    focusManager?.updateGlobalFocusCount();

    // 更新语义
    _semanticsOwner?.sendSemanticsUpdate();
  }
}

BuildOwner与WidgetsBinding的关系:

BuildOwner是由WidgetsBinding创建和管理的:

// packages/flutter/lib/src/widgets/binding.dart
mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding, GestureBinding, RendererBinding, SemanticsBinding {
  // BuildOwner实例
  BuildOwner? _buildOwner;
  BuildOwner? get buildOwner => _buildOwner;

  // 初始化
  
  void initInstances() {
    super.initInstances();

    // 创建BuildOwner
    _buildOwner = BuildOwner(
      onBuildScheduled: _handleBuildScheduled,
      focusManager: focusManager,
    );
  }

  // 处理构建调度
  void _handleBuildScheduled() {
    // 确保我们会收到下一帧的回调
    ensureVisualUpdate();
  }
}

更新调度流程:

  1. 当调用setState时,关联的Element被标记为dirty
  2. Element调用BuildOwner.scheduleBuildFor将自己添加到脏元素列表
  3. BuildOwner触发onBuildScheduled回调,实际上是_handleBuildScheduled
  4. _handleBuildScheduled调用ensureVisualUpdate,它会调用scheduleFrame
  5. scheduleFrame请求一个新的帧
  6. 在下一个VSync信号到来时,引擎调用handleBeginFramehandleDrawFrame
  7. handleDrawFrame中,WidgetsBinding.drawFrame被调用
  8. drawFrame调用buildOwner.buildScope重建所有脏元素

BuildOwner的高效设计:

  1. 批量处理: 将所有脏元素收集起来一次性处理,避免重复构建
  2. 深度排序: 按照深度排序脏元素,确保父元素在子元素之前重建
  3. 延迟构建: 直到下一帧才进行构建,避免不必要的中间状态
  4. 构建边界: 仅重建标记为脏的元素及其子树,而不是整个UI树

5.3 setState内部实现

setState是Flutter状态管理的核心API,它触发UI更新的整个过程。让我们深入分析它的内部实现。

State类的设计:

// packages/flutter/lib/src/widgets/framework.dart
abstract class State<T extends StatefulWidget> {
  // 当前widget引用
  T get widget => _widget as T;
  T _widget;

  // 关联的Element
  StatefulElement? _element;

  // 状态生命周期
  _StateLifecycle _debugLifecycleState = _StateLifecycle.created;

  // setState方法
  
  void setState(VoidCallback fn) {
    // 各种断言检查
    assert(() {
      if (_debugLifecycleState == _StateLifecycle.defunct) {
        throw FlutterError.fromParts(<DiagnosticsNode>[
          ErrorSummary('setState() called after dispose()'),
          // 更多错误信息...
        ]);
      }
      if (_debugLifecycleState == _StateLifecycle.build) {
        throw FlutterError.fromParts(<DiagnosticsNode>[
          ErrorSummary('setState() called during build'),
          // 更多错误信息...
        ]);
      }
      return true;
    }());

    // 执行状态更新函数
    fn();

    // 标记Element需要重建
    _element!.markNeedsBuild();
  }

  // 构建方法(子类必须实现)
  
  Widget build(BuildContext context);

  // 生命周期方法
  
  void initState() { }

  
  void didUpdateWidget(covariant T oldWidget) { }

  
  void dispose() { }
}

setState的核心实现:

setState方法的实现非常简洁:


void setState(VoidCallback fn) {
  // 执行状态更新函数
  fn();

  // 标记Element需要重建
  _element!.markNeedsBuild();
}

它做了两件事:

  1. 执行传入的回调函数,更新状态变量
  2. 调用关联Element的markNeedsBuild方法,触发UI更新

markNeedsBuild的实现:

// packages/flutter/lib/src/widgets/framework.dart
void markNeedsBuild() {
  // 如果已经标记为dirty,直接返回
  if (_dirty)
    return;

  // 检查Element是否还活跃
  if (!_active)
    return;

  // 标记为dirty
  _dirty = true;

  // 将Element添加到BuildOwner的待重建列表
  owner!.scheduleBuildFor(this);
}

setState的调用约束:

从源码中的断言可以看出,setState有以下调用约束:

  1. 不能在build方法中调用
  2. 不能在dispose后调用
  3. 必须在有效的State生命周期中调用

setState与Element的关联:

State和Element的关联在StatefulElement的构造函数中建立:

// packages/flutter/lib/src/widgets/framework.dart
StatefulElement(StatefulWidget widget)
    : _state = widget.createState(),
      super(widget) {
  // 将state与element关联
  _state._element = this;
  _state._widget = widget;
}

状态更新的细节:

当调用setState时,实际的Widget更新发生在下一帧的build阶段:

// packages/flutter/lib/src/widgets/framework.dart
class StatefulElement extends ComponentElement {
  // ...

  
  Widget build() {
    // 调用state.build获取新的Widget树
    return _state.build(this);
  }

  
  void performRebuild() {
    // 先调用didUpdateWidget(如果需要)
    if (_didUpdateWidget) {
      _state.didUpdateWidget(oldWidget);
      _didUpdateWidget = false;
    }

    // 然后进行标准的重建流程
    super.performRebuild();
  }
}

异步setState的处理:

Flutter允许在异步上下文中调用setState:

Future<void> fetchData() async {
  final response = await http.get('https://api.example.com/data');
  setState(() {
    _data = jsonDecode(response.body);
  });
}

这是因为Element和State的生命周期是框架管理的,只要State对象存在且与活跃的Element关联,就可以调用setState触发更新。

批量更新的实现:

多次调用setState会被批量处理:

// 示例: 连续调用setState
void updateMultipleTimes() {
  setState(() => _counter += 1);
  setState(() => _text = 'Updated');
  setState(() => _color = Colors.red);
}

这是因为markNeedsBuild只是将Element添加到脏列表,实际重建发生在下一帧,所以多次更新会合并为一次重建。

总结:

setState是Flutter状态管理的核心机制,它通过简洁的API隐藏了复杂的状态更新流程。通过深入理解其内部实现,可以更好地掌握Flutter的响应式UI模型,编写高效的状态管理代码。

6. 事件处理与手势识别

Flutter的事件处理系统是一套精心设计的机制,用于接收、分发和处理用户输入。本节将深入分析Flutter事件传递路径、手势识别竞技场和事件分发处理机制。

6.1 事件传递路径

Flutter的事件系统从底层平台事件开始,经过多层转换和分发,最终到达具体的Widget。整个过程如下:

事件传递完整路径:

平台事件(Android/iOS) → Engine(C++) → Window(Dart) →
GestureBinding → HitTestResult → RenderObject树(自上而下) →
事件分发(自下而上) → GestureDetector/Listener → 回调函数

1. 从平台到Flutter引擎:

平台原生事件(如触摸、键盘)首先由操作系统捕获,然后传递给Flutter引擎:

// engine/src/flutter/shell/platform/android/android_shell_holder.cc (Android)
void AndroidShellHolder::DispatchPointerDataPacket(
    std::unique_ptr<flutter::PointerDataPacket> packet) {
  // 将指针事件传递给引擎
  engine_->DispatchPointerDataPacket(std::move(packet));
}

// engine/src/flutter/lib/ui/window/window.cc
void Window::DispatchPointerDataPacket(const PointerDataPacket& packet) {
  // 引擎将事件转换为Dart可理解的格式,并传递给Dart代码
  std::vector<uint8_t> data = packet.data();
  UIDartState::Current()->OnPointerDataPacket(data);
}

2. 从引擎到Dart层:

事件到达Dart层后,由Window类接收并传递给GestureBinding:

// packages/flutter/lib/src/gestures/binding.dart

void onPointerDataPacket(ui.PointerDataPacket packet) {
  // 将指针数据转换为PointerEvent对象
  final List<PointerEvent> pointerEvents = PointerEventConverter.expand(
    packet.data,
    _pointerState.devicePixelRatio,
  );

  // 分发事件
  if (pointerEvents.isNotEmpty)
    _handlePointerEvents(pointerEvents);
}

3. 命中测试:

事件到达后,Flutter需要确定哪些对象应该接收事件,这通过命中测试(Hit Testing)实现:

// packages/flutter/lib/src/gestures/binding.dart
void _handlePointerEvents(Iterable<PointerEvent> events) {
  // 处理每个事件
  for (final PointerEvent event in events) {
    // 为每个指针跟踪事件历史
    final HitTestResult? hitTestResult = _hitTests[event.pointer];

    // 如果是按下事件,执行命中测试
    if (event is PointerDownEvent) {
      // 创建一个新的命中测试结果
      final HitTestResult result = HitTestResult();
      // 执行命中测试,从根开始
      hitTest(result, event.position);
      // 存储此指针的命中测试结果
      _hitTests[event.pointer] = result;

      // 将命中测试结果转发给其他处理器
      dispatchEvent(event, result);
    } else if (hitTestResult != null) {
      // 对于其他事件,使用已保存的命中测试结果
      dispatchEvent(event, hitTestResult);
    }
  }
}

4. 命中测试从根RenderObject开始:

命中测试从RenderView(根RenderObject)开始,向下遍历整个RenderObject树:

// packages/flutter/lib/src/rendering/view.dart

bool hitTest(HitTestResult result, { required Offset position }) {
  // 首先将自己添加到命中测试结果
  if (child != null)
    child!.hitTest(BoxHitTestResult.wrap(result), position: position);

  // 总是返回true,因为这是根视图
  return true;
}

5. RenderObject树的命中测试:

命中测试递归地遍历RenderObject树,每个RenderObject决定是否命中以及是否继续传递给子节点:

// packages/flutter/lib/src/rendering/box.dart

bool hitTest(BoxHitTestResult result, { required Offset position }) {
  // 检查位置是否在此RenderBox的边界内
  if (_size.contains(position)) {
    // 首先测试子节点
    if (hitTestChildren(result, position: position) || hitTestSelf(position)) {
      // 如果命中,将自己添加到结果中
      result.add(BoxHitTestEntry(this, position));
      return true;
    }
  }
  return false;
}

6. 自定义RenderObject的命中测试示例:

RenderPointerListener是一个专门处理指针事件的RenderObject:

// packages/flutter/lib/src/rendering/proxy_box.dart

bool hitTestSelf(Offset position) => behavior != HitTestBehavior.deferToChild;


bool hitTestChildren(BoxHitTestResult result, {required Offset position}) {
  if (behavior == HitTestBehavior.opaque)
    return false;
  return super.hitTestChildren(result, position: position);
}

7. 事件分发:

一旦命中测试完成,事件会按照命中测试结果的相反顺序分发:

// packages/flutter/lib/src/gestures/binding.dart

void dispatchEvent(PointerEvent event, HitTestResult hitTestResult) {
  // 按照命中测试结果的相反顺序分发事件(从叶子节点到根节点)
  for (final HitTestEntry entry in hitTestResult.path) {
    try {
      entry.target.handleEvent(event.transformed(entry.transform), entry);
    } catch (exception, stack) {
      // 处理错误...
    }
  }
}

8. 在RenderObject中处理事件:

每个RenderObject可以选择如何处理事件:

// packages/flutter/lib/src/rendering/proxy_box.dart

void handleEvent(PointerEvent event, HitTestEntry entry) {
  // RenderPointerListener处理指针事件
  assert(debugHandleEvent(event, entry));
  if (onPointerDown != null && event is PointerDownEvent)
    onPointerDown!(event);
  if (onPointerMove != null && event is PointerMoveEvent)
    onPointerMove!(event);
  if (onPointerUp != null && event is PointerUpEvent)
    onPointerUp!(event);
  if (onPointerCancel != null && event is PointerCancelEvent)
    onPointerCancel!(event);
  if (onPointerSignal != null && event is PointerSignalEvent)
    onPointerSignal!(event);
}

9. 从RenderObject到Widget:

事件从RenderObject传递到Widget层,通常通过如下方式:

// packages/flutter/lib/src/widgets/gesture_detector.dart
class RenderSemanticsGestureHandler extends RenderProxyBox {
  // ...

  
  void handleEvent(PointerEvent event, HitTestEntry entry) {
    // 将事件转发给回调
    if (onTap != null && event is PointerUpEvent)
      onTap!();
    // ...
  }
}

10. GestureDetector的实现:

最终,用户通过GestureDetector等Widget接收事件:

// packages/flutter/lib/src/widgets/gesture_detector.dart
class GestureDetector extends StatelessWidget {
  // ...

  
  Widget build(BuildContext context) {
    // 创建手势识别器
    final Map<Type, GestureRecognizerFactory> gestures = <Type, GestureRecognizerFactory>{};

    // 配置点击识别器
    if (onTap != null || onTapDown != null || /* ... */) {
      gestures[TapGestureRecognizer] = GestureRecognizerFactoryWithHandlers<TapGestureRecognizer>(
        () => TapGestureRecognizer(debugOwner: this),
        (TapGestureRecognizer instance) {
          instance
            ..onTapDown = onTapDown
            ..onTapUp = onTapUp
            ..onTap = onTap
            // ...
        },
      );
    }

    // 创建RawGestureDetector
    Widget result = RawGestureDetector(
      gestures: gestures,
      behavior: behavior,
      child: child,
    );

    return result;
  }
}

通过这个完整的事件传递路径,Flutter能够精确地将用户输入传递给正确的Widget,实现响应式的交互体验。

6.2 手势识别竞技场

Flutter的手势识别系统采用"竞技场"模式,允许多个手势识别器竞争同一事件流,最终确定哪个识别器"胜出"。

手势竞技场的核心概念:

  1. 手势识别器(GestureRecognizer): 识别特定模式的触摸序列
  2. 竞技场(Arena): 管理识别器之间的竞争
  3. 仲裁机制: 决定哪个识别器最终处理手势

GestureArena源码:

// packages/flutter/lib/src/gestures/arena.dart
class GestureArenaManager {
  // 存储每个指针ID对应的竞技场
  final Map<int, GestureArenaEntry> _arenas = <int, GestureArenaEntry>{};

  // 添加成员到竞技场
  GestureArenaEntry add(int pointer, GestureArenaMember member) {
    // 获取或创建竞技场
    GestureArenaEntry? entry = _arenas[pointer];
    if (entry == null) {
      entry = GestureArenaEntry._(this, pointer);
      _arenas[pointer] = entry;
    }

    // 添加成员
    entry._members.add(member);

    return entry;
  }

  // 关闭竞技场,不再接受新成员
  void close(int pointer) {
    final GestureArenaEntry? entry = _arenas[pointer];
    if (entry == null)
      return;

    entry._isOpen = false;
    _tryToResolveArena(pointer, entry);
  }

  // 某个成员宣布胜出
  void sweep(int pointer) {
    final GestureArenaEntry? entry = _arenas[pointer];
    if (entry == null)
      return;

    // 如果只有一个成员,它直接胜出
    if (entry._members.length == 1) {
      final GestureArenaMember member = entry._members.first;
      entry._members.clear();
      _arenas.remove(pointer);
      member.acceptGesture(pointer);
      return;
    }

    // 否则,拒绝所有成员
    if (entry._members.isNotEmpty) {
      final List<GestureArenaMember> members = List<GestureArenaMember>.from(entry._members);
      entry._members.clear();
      _arenas.remove(pointer);
      for (final GestureArenaMember member in members)
        member.rejectGesture(pointer);
    }
  }

  // 尝试解决竞技场
  void _tryToResolveArena(int pointer, GestureArenaEntry entry) {
    // 如果竞技场关闭且只有一个成员,它胜出
    if (!entry._isOpen && entry._members.length == 1) {
      final GestureArenaMember member = entry._members.first;
      entry._members.clear();
      _arenas.remove(pointer);
      member.acceptGesture(pointer);
      return;
    }

    // 如果竞技场关闭且没有成员,移除竞技场
    if (!entry._isOpen && entry._members.isEmpty) {
      _arenas.remove(pointer);
    }
  }
}

手势识别器的基类:

// packages/flutter/lib/src/gestures/recognizer.dart
abstract class GestureRecognizer extends GestureArenaMember with DiagnosticableTreeMixin {
  // 添加指针
  
  void addPointer(PointerDownEvent event) {
    // 注册到竞技场
    _entries[event.pointer] = GestureBinding.instance.gestureArena.add(event.pointer, this);
  }

  // 开始跟踪指针
  void startTrackingPointer(int pointer, [Matrix4? transform]) {
    GestureBinding.instance.pointerRouter.addRoute(pointer, handleEvent, transform);
  }

  // 停止跟踪指针
  void stopTrackingPointer(int pointer) {
    GestureBinding.instance.pointerRouter.removeRoute(pointer, handleEvent);
  }

  // 处理事件(子类实现)
  void handleEvent(PointerEvent event);

  // 竞技场回调:接受手势
  
  void acceptGesture(int pointer) { }

  // 竞技场回调:拒绝手势
  
  void rejectGesture(int pointer) { }
}

手势识别器示例 - TapGestureRecognizer:

// packages/flutter/lib/src/gestures/tap.dart
class TapGestureRecognizer extends PrimaryPointerGestureRecognizer {
  // 事件回调
  GestureTapDownCallback? onTapDown;
  GestureTapUpCallback? onTapUp;
  GestureTapCallback? onTap;
  GestureTapCancelCallback? onTapCancel;

  // 状态变量
  bool _sentTapDown = false;
  bool _wonArenaForPrimaryPointer = false;
  Offset? _finalPosition;

  // 处理指针按下事件
  
  void handlePrimaryPointer(PointerEvent event) {
    if (event is PointerUpEvent) {
      _finalPosition = event.position;
      // 检查是否胜出
      _checkUp();
    } else if (event is PointerCancelEvent) {
      _reset();
    }
  }

  // 竞技场回调:接受手势
  
  void acceptGesture(int pointer) {
    if (pointer == primaryPointer) {
      _wonArenaForPrimaryPointer = true;
      _checkUp();
    }
  }

  // 竞技场回调:拒绝手势
  
  void rejectGesture(int pointer) {
    if (pointer == primaryPointer) {
      // 发送取消事件
      if (_sentTapDown) {
        if (onTapCancel != null)
          onTapCancel!();
      }
      _reset();
    }
  }

  // 检查是否应该触发点击事件
  void _checkUp() {
    if (_wonArenaForPrimaryPointer && _finalPosition != null) {
      // 如果胜出且有最终位置,触发点击事件
      if (onTapUp != null) {
        onTapUp!(TapUpDetails(
          kind: getKindForPointer(primaryPointer!),
          globalPosition: _finalPosition!,
          localPosition: _finalPosition!, // 简化版本
        ));
      }
      if (onTap != null)
        onTap!();
      _reset();
    }
  }

  // 重置状态
  void _reset() {
    _sentTapDown = false;
    _wonArenaForPrimaryPointer = false;
    _finalPosition = null;
  }
}

竞争解决机制:

  1. 明确放弃: 某个识别器可以显式放弃竞争
// packages/flutter/lib/src/gestures/recognizer.dart
void resolve(GestureDisposition disposition) {
  final List<int> localKeys = List<int>.from(_entries.keys);
  for (final int pointer in localKeys) {
    final GestureArenaEntry? entry = _entries[pointer];
    if (entry != null) {
      entry.resolve(disposition);
    }
  }
}
  1. 优先级: 有些识别器具有更高的优先级
// 例如,SingleChildScrollView的识别器可以在垂直滚动方向上获得优先权
void _handleDragStart(DragStartDetails details) {
  // 如果是垂直方向滚动,则更有可能获胜
  if (widget.scrollDirection == Axis.vertical) {
    // ...
  }
}
  1. 竞技场关闭: 当指针抬起时,竞技场关闭并强制解决
// packages/flutter/lib/src/gestures/binding.dart
void _handlePointerEventImmediately(PointerEvent event) {
  // ...
  if (event is PointerUpEvent || event is PointerCancelEvent) {
    // 关闭竞技场
    gestureArena.close(event.pointer);
  } else if (event is PointerDownEvent) {
    // 为此指针创建竞技场
    gestureArena.open(event.pointer);
  }
  // ...
}

手势竞技场的优势:

  1. 消除歧义: 处理复杂的多手势情况,如区分点击和拖动
  2. 延迟决策: 可以等待更多信息再做决定
  3. 层次结构: 允许父子Widget都有机会处理手势
  4. 动态适应: 可以根据手势的发展改变决策

这种竞技场机制使Flutter能够处理复杂的手势交互,同时保持代码的模块化和可扩展性。

6.3 事件分发与处理

事件分发是Flutter事件系统的核心机制,它确保事件能够正确地传递给相应的处理者。

事件分发的核心组件:

  1. PointerRouter: 管理指针事件的路由
  2. HitTestResult: 存储命中测试的结果
  3. GestureBinding: 协调整个事件系统

PointerRouter源码:

// packages/flutter/lib/src/gestures/pointer_router.dart
class PointerRouter {
  // 存储每个指针ID对应的路由表
  final Map<int, Map<PointerRoute, Matrix4?>> _routeMap = <int, Map<PointerRoute, Matrix4?>>{};

  // 添加路由
  void addRoute(int pointer, PointerRoute route, [Matrix4? transform]) {
    final Map<PointerRoute, Matrix4?> routes = _routeMap.putIfAbsent(
      pointer,
      () => <PointerRoute, Matrix4?>{},
    );
    routes[route] = transform;
  }

  // 移除路由
  void removeRoute(int pointer, PointerRoute route) {
    final Map<PointerRoute, Matrix4?>? routes = _routeMap[pointer];
    if (routes != null) {
      routes.remove(route);
      if (routes.isEmpty)
        _routeMap.remove(pointer);
    }
  }

  // 分发事件
  void route(PointerEvent event) {
    final Map<PointerRoute, Matrix4?>? routes = _routeMap[event.pointer];
    if (routes == null)
      return;

    // 复制路由表,防止在迭代过程中修改
    final List<PointerRoute> callbackRoutes = routes.keys.toList();
    final List<Matrix4?> transforms = routes.values.toList();

    // 调用所有路由
    for (int i = 0; i < callbackRoutes.length; i++) {
      try {
        callbackRoutes[i](
          event.transformed(transforms[i])
        );
      } catch (exception, stack) {
        // 处理错误...
      }
    }
  }
}

事件分发流程:

  1. 接收原始事件:
// packages/flutter/lib/src/gestures/binding.dart

void onPointerDataPacket(ui.PointerDataPacket packet) {
  // 将原始数据转换为PointerEvent对象
  final List<PointerEvent> pointerEvents = PointerEventConverter.expand(
    packet.data,
    _pointerState.devicePixelRatio,
  );

  // 处理事件
  if (pointerEvents.isNotEmpty)
    _handlePointerEvents(pointerEvents);
}
  1. 执行命中测试:
// packages/flutter/lib/src/gestures/binding.dart
void _handlePointerEvents(Iterable<PointerEvent> events) {
  for (final PointerEvent event in events) {
    if (event is PointerDownEvent) {
      // 执行命中测试
      final HitTestResult result = HitTestResult();
      hitTest(result, event.position);
      _hitTests[event.pointer] = result;
    }
    // 分发事件
    dispatchEvent(event, _hitTests[event.pointer]);
  }
}
  1. 分发事件到命中对象:
// packages/flutter/lib/src/gestures/binding.dart

void dispatchEvent(PointerEvent event, HitTestResult? hitTestResult) {
  // 首先路由事件到直接监听者
  _pointerRouter.route(event);

  // 然后路由到命中测试结果
  if (hitTestResult != null) {
    for (final HitTestEntry entry in hitTestResult.path) {
      entry.target.handleEvent(event.transformed(entry.transform), entry);
    }
  }
}

渲染对象中的事件处理:

渲染对象实现handleEvent方法来处理事件:

// packages/flutter/lib/src/rendering/proxy_box.dart
class RenderPointerListener extends RenderProxyBox {
  // 事件回调
  PointerDownEventListener? onPointerDown;
  PointerMoveEventListener? onPointerMove;
  PointerUpEventListener? onPointerUp;
  PointerCancelEventListener? onPointerCancel;

  
  void handleEvent(PointerEvent event, BoxHitTestEntry entry) {
    assert(debugHandleEvent(event, entry));
    // 根据事件类型调用相应回调
    if (onPointerDown != null && event is PointerDownEvent)
      onPointerDown!(event);
    if (onPointerMove != null && event is PointerMoveEvent)
      onPointerMove!(event);
    if (onPointerUp != null && event is PointerUpEvent)
      onPointerUp!(event);
    if (onPointerCancel != null && event is PointerCancelEvent)
      onPointerCancel!(event);
  }
}

手势识别器的事件处理:

手势识别器通过PointerRouter接收事件:

// packages/flutter/lib/src/gestures/recognizer.dart
abstract class OneSequenceGestureRecognizer extends GestureRecognizer {
  final Map<int, GestureArenaEntry> _entries = <int, GestureArenaEntry>{};

  // 添加指针并开始跟踪
  
  void addPointer(PointerDownEvent event) {
    // 注册到竞技场
    _entries[event.pointer] = GestureBinding.instance.gestureArena.add(event.pointer, this);
    // 开始跟踪指针
    startTrackingPointer(event.pointer);
  }

  // 处理事件
  
  void handleEvent(PointerEvent event) {
    if (event is PointerDownEvent) {
      // 处理按下事件
      handlePrimaryPointer(event);
    } else if (event.pointer == primaryPointer) {
      // 处理主指针的事件
      handlePrimaryPointer(event);
    } else {
      // 处理辅助指针的事件
      handleSecondaryPointer(event);
    }
  }
}

Listener和GestureDetector的关系:

Listener直接处理低级指针事件,而GestureDetector使用手势识别器处理高级手势:

// packages/flutter/lib/src/widgets/gesture_detector.dart
class GestureDetector extends StatelessWidget {
  
  Widget build(BuildContext context) {
    // 创建手势识别器
    final Map<Type, GestureRecognizerFactory> gestures = <Type, GestureRecognizerFactory>{};

    // 配置识别器...

    // 创建RawGestureDetector
    Widget result = RawGestureDetector(
      gestures: gestures,
      behavior: behavior,
      child: child,
    );

    // 额外的Listener配置
    if (onPointerDown != null ||
        onPointerMove != null ||
        onPointerUp != null ||
        onPointerCancel != null) {
      result = Listener(
        onPointerDown: onPointerDown,
        onPointerMove: onPointerMove,
        onPointerUp: onPointerUp,
        onPointerCancel: onPointerCancel,
        child: result,
      );
    }

    return result;
  }
}

自定义事件处理示例:

以下是实现自定义手势识别器的示例:

class CustomTapGestureRecognizer extends TapGestureRecognizer {
  // 自定义属性
  final Duration maxTime;

  CustomTapGestureRecognizer({
    required Object debugOwner,
    this.maxTime = const Duration(milliseconds: 300),
  }) : super(debugOwner: debugOwner);

  // 记录按下时间
  DateTime? _downTime;

  
  void handlePrimaryPointer(PointerEvent event) {
    if (event is PointerDownEvent) {
      _downTime = DateTime.now();
    } else if (event is PointerUpEvent) {
      // 检查时间间隔
      final timeDiff = DateTime.now().difference(_downTime!);
      if (timeDiff > maxTime) {
        // 如果超过最大时间,放弃竞技场
        resolve(GestureDisposition.rejected);
        return;
      }
    }
    // 调用父类处理方法
    super.handlePrimaryPointer(event);
  }
}

通过这种分层的事件处理机制,Flutter可以灵活地处理各种复杂的交互场景,同时保持代码的清晰和模块化。

7. 动画系统实现

Flutter的动画系统是构建流畅、精美用户界面的重要组成部分。本节将深入分析Flutter动画系统的核心实现,包括Ticker机制、动画控制器和动画插值计算。

7.1 Ticker与SchedulerBinding

Flutter的动画系统基于"tick"机制,即屏幕刷新时的回调通知。这一机制由Ticker和SchedulerBinding共同实现。

Ticker的核心概念:

Ticker是一个简单的计时器,它在每一帧到来时调用回调函数。Ticker本身不驱动动画,而是提供了时间信号。

Ticker源码:

// packages/flutter/lib/src/scheduler/ticker.dart
class Ticker {
  // 构造函数
  Ticker(this._onTick, { this.debugLabel });

  // 帧回调函数
  final TickerCallback _onTick;

  // 调试标签
  final String? debugLabel;

  // 开始时间
  Duration? _startTime;

  // 是否启用
  bool _active = false;

  // 是否暂停
  bool _muted = false;

  // 启动Ticker
  void start() {
    // 已经启动则直接返回
    if (_active)
      return;

    // 标记为活跃
    _active = true;

    // 如果未静音,注册帧回调
    if (!_muted)
      _startTicker();
  }

  // 停止Ticker
  void stop({ bool canceled = false }) {
    if (!_active)
      return;

    // 标记为非活跃
    _active = false;

    // 如果已注册帧回调,取消注册
    if (_animationId != null) {
      SchedulerBinding.instance.cancelFrameCallbackWithId(_animationId!);
      _animationId = null;
    }
  }

  // 内部ID
  int? _animationId;

  // 启动内部Ticker
  void _startTicker() {
    assert(_active);
    assert(_animationId == null);

    // 注册帧回调
    _animationId = SchedulerBinding.instance.scheduleFrameCallback(_tick);

    // 记录启动时间
    _startTime ??= SchedulerBinding.instance.currentFrameTime;
  }

  // 每帧回调
  void _tick(Duration timeStamp) {
    // 取消当前的帧回调ID
    _animationId = null;

    // 如果暂停或停止,直接返回
    if (!_active || _muted)
      return;

    // 计算流逝的时间
    final Duration elapsedDuration = timeStamp - (_startTime ?? timeStamp);

    // 调用回调
    _onTick(elapsedDuration);

    // 如果仍然活跃且未静音,注册下一帧回调
    if (_active && !_muted)
      _animationId = SchedulerBinding.instance.scheduleFrameCallback(_tick);
  }
}

SchedulerBinding的角色:

SchedulerBinding是连接Flutter引擎和框架的纽带之一,负责处理VSync信号和帧回调。

// packages/flutter/lib/src/scheduler/binding.dart
mixin SchedulerBinding on BindingBase implements ServicesBinding {
  // 帧回调列表
  final List<FrameCallback> _persistentCallbacks = <FrameCallback>[];

  // 瞬态回调映射
  final Map<int, _FrameCallbackEntry> _transientCallbacks = <int, _FrameCallbackEntry>{};

  // 下一个回调ID
  int _nextCallbackId = 0;

  // 调度帧回调
  int scheduleFrameCallback(FrameCallback callback, { bool rescheduling = false }) {
    // 生成回调ID
    final int id = _nextCallbackId += 1;

    // 添加到瞬态回调映射
    _transientCallbacks[id] = _FrameCallbackEntry(callback, rescheduling);

    // 请求新的一帧
    if (_hasScheduledFrame)
      return id;
    if (handleScheduleFrame != null) {
      handleScheduleFrame!();
    } else {
      scheduleFrame();
    }
    return id;
  }

  // 取消帧回调
  void cancelFrameCallbackWithId(int id) {
    _transientCallbacks.remove(id);
  }

  // 处理帧开始
  void handleBeginFrame(Duration? rawTimeStamp) {
    Timeline.startSync('Frame', arguments: timelineWhitelistArguments);

    // 设置当前帧时间戳
    _currentFrameTimeStamp = _adjustForEpoch(rawTimeStamp ?? _lastRawTimeStamp);

    // 如果处于空闲状态,处理瞬态回调
    if (_schedulerPhase == SchedulerPhase.idle) {
      _schedulerPhase = SchedulerPhase.transientCallbacks;
      try {
        _invokeTransientFrameCallbacks(_currentFrameTimeStamp!);
      } finally {
        _schedulerPhase = SchedulerPhase.midFrameMicrotasks;
      }
    }
  }

  // 调用瞬态帧回调
  void _invokeTransientFrameCallbacks(Duration timeStamp) {
    final Map<int, _FrameCallbackEntry> callbacks = _transientCallbacks;
    _transientCallbacks = <int, _FrameCallbackEntry>{};

    callbacks.forEach((int id, _FrameCallbackEntry callbackEntry) {
      if (!_removedIds.contains(id)) {
        _invokeFrameCallback(callbackEntry.callback, timeStamp, callbackEntry.debugStack);
      }
    });
  }
}

TickerProvider的作用:

TickerProvider是一个抽象接口,用于创建Ticker。通常由StatefulWidget的State实现,以便在widget生命周期内管理Ticker。

// packages/flutter/lib/src/scheduler/ticker.dart
abstract class TickerProvider {
  // 创建Ticker
  Ticker createTicker(TickerCallback onTick);
}

// 单Ticker提供者
mixin SingleTickerProviderStateMixin<T extends StatefulWidget> on State<T> implements TickerProvider {
  Ticker? _ticker;

  
  Ticker createTicker(TickerCallback onTick) {
    assert(_ticker == null);
    _ticker = Ticker(onTick, debugLabel: 'created by ${widget.runtimeType}');
    return _ticker!;
  }

  
  void dispose() {
    // 确保Ticker在State销毁时也被销毁
    _ticker?.dispose();
    super.dispose();
  }
}

Ticker与动画的连接:

Ticker为动画系统提供了时间信号,动画控制器使用这些信号来驱动动画状态更新:

// AnimationController构造时需要TickerProvider
AnimationController controller = AnimationController(
  vsync: this, // 提供Ticker
  duration: Duration(seconds: 1),
);

// 内部创建Ticker
_ticker = vsync.createTicker(_tick);

// 在每一帧回调中更新动画值
void _tick(Duration elapsed) {
  // 更新动画值
  value = _simulation.x(elapsed.inMicroseconds.toDouble() / Duration.microsecondsPerSecond);

  // 如果动画结束,停止Ticker
  if (_simulation.isDone(elapsed.inMicroseconds.toDouble() / Duration.microsecondsPerSecond)) {
    stop();
  }
}

7.2 动画控制器与驱动

AnimationController是Flutter动画系统的核心控制器,负责管理动画的状态和进度。

AnimationController源码:

// packages/flutter/lib/src/animation/animation_controller.dart
class AnimationController extends Animation<double>
  with AnimationEagerListenerMixin, AnimationLocalListenersMixin, AnimationLocalStatusListenersMixin {
  // 构造函数
  AnimationController({
    double? value,
    this.duration,
    this.reverseDuration,
    this.debugLabel,
    this.lowerBound = 0.0,
    this.upperBound = 1.0,
    this.animationBehavior = AnimationBehavior.normal,
    required TickerProvider vsync,
  }) : _direction = _AnimationDirection.forward {
    // 创建Ticker
    _ticker = vsync.createTicker(_tick);

    // 设置初始值
    _internalSetValue(value ?? lowerBound);
  }

  // Ticker引用
  late final Ticker _ticker;

  // 动画值
  double _value = 0.0;

  // 动画方向
  _AnimationDirection _direction;

  // 动画状态
  AnimationStatus _status = AnimationStatus.dismissed;

  // 动画模拟器(控制动画曲线)
  Simulation? _simulation;

  // 获取动画值
  
  double get value => _value;

  // 设置动画值
  set value(double newValue) {
    // 停止当前动画
    stop();

    // 设置新值
    _internalSetValue(newValue);

    // 通知监听器
    notifyListeners();
    _checkStatusChanged();
  }

  // 内部设置值
  void _internalSetValue(double newValue) {
    // 确保值在范围内
    _value = clampDouble(newValue, lowerBound, upperBound);
  }

  // 正向运行动画
  TickerFuture forward({ double? from }) {
    // 设置起始值
    if (from != null)
      value = from;

    // 设置方向和状态
    _direction = _AnimationDirection.forward;
    if (value == upperBound) {
      _status = AnimationStatus.completed;
      return TickerFuture.complete();
    }

    // 如果动画被禁用,直接完成
    if (_ticker.muted) {
      _status = AnimationStatus.forward;
      value = upperBound;
      _status = AnimationStatus.completed;
      return TickerFuture.complete();
    }

    // 设置状态
    _status = AnimationStatus.forward;

    // 创建动画模拟器
    return _animateToInternal(upperBound);
  }

  // 反向运行动画
  TickerFuture reverse({ double? from }) {
    // 设置起始值
    if (from != null)
      value = from;

    // 设置方向和状态
    _direction = _AnimationDirection.reverse;
    if (value == lowerBound) {
      _status = AnimationStatus.dismissed;
      return TickerFuture.complete();
    }

    // 如果动画被禁用,直接完成
    if (_ticker.muted) {
      _status = AnimationStatus.reverse;
      value = lowerBound;
      _status = AnimationStatus.dismissed;
      return TickerFuture.complete();
    }

    // 设置状态
    _status = AnimationStatus.reverse;

    // 创建动画模拟器
    return _animateToInternal(lowerBound);
  }

  // 动画到指定值
  TickerFuture animateTo(double target, { Duration? duration, Curve curve = Curves.linear }) {
    // 设置方向
    if (target > value) {
      _direction = _AnimationDirection.forward;
    } else if (target < value) {
      _direction = _AnimationDirection.reverse;
    }

    // 设置状态
    _status = (_direction == _AnimationDirection.forward)
      ? AnimationStatus.forward
      : AnimationStatus.reverse;

    // 创建动画模拟器
    return _animateToInternal(target, duration: duration, curve: curve);
  }

  // 内部动画实现
  TickerFuture _animateToInternal(double target, { Duration? duration, Curve curve = Curves.linear }) {
    // 停止当前动画
    stop();

    // 如果已经到达目标,直接返回
    if (target == value)
      return TickerFuture.complete();

    // 计算动画时长
    Duration calculatedDuration;
    if (duration == null) {
      final double range = upperBound - lowerBound;
      final double remainingFraction = (target - value).abs() / range;
      calculatedDuration = this.duration! * remainingFraction;
    } else {
      calculatedDuration = duration;
    }

    // 创建模拟器
    _simulation = _InterpolationSimulation(value, target, calculatedDuration, curve);

    // 启动Ticker
    return _ticker.start();
  }

  // 每帧回调
  void _tick(Duration elapsed) {
    // 计算动画值
    _value = _simulation!.x(elapsed.inMicroseconds.toDouble() / Duration.microsecondsPerSecond);

    // 如果动画结束
    if (_simulation!.isDone(elapsed.inMicroseconds.toDouble() / Duration.microsecondsPerSecond)) {
      _status = (_direction == _AnimationDirection.forward)
        ? AnimationStatus.completed
        : AnimationStatus.dismissed;
      stop();
    }

    // 通知监听器
    notifyListeners();
  }

  // 停止动画
  void stop({ bool canceled = false }) {
    // 停止Ticker
    _ticker.stop(canceled: canceled);

    // 清除模拟器
    _simulation = null;
  }

  // 释放资源
  void dispose() {
    // 释放Ticker
    _ticker.dispose();
    super.dispose();
  }
}

动画驱动器的类型:

Flutter的动画系统使用物理模拟(Simulation)来驱动动画。主要的模拟器包括:

  1. _InterpolationSimulation: 基于插值的简单模拟器
  2. SpringSimulation: 弹簧物理模拟
  3. GravitySimulation: 重力物理模拟
  4. FrictionSimulation: 摩擦物理模拟

_InterpolationSimulation源码:

// packages/flutter/lib/src/animation/animation_controller.dart
class _InterpolationSimulation extends Simulation {
  _InterpolationSimulation(
    this._begin,
    this._end,
    Duration duration,
    this._curve,
  ) : _durationInSeconds = duration.inMicroseconds.toDouble() / Duration.microsecondsPerSecond;

  final double _begin;
  final double _end;
  final double _durationInSeconds;
  final Curve _curve;

  
  double x(double timeInSeconds) {
    final double t = clampDouble(timeInSeconds / _durationInSeconds, 0.0, 1.0);
    if (t == 0.0)
      return _begin;
    if (t == 1.0)
      return _end;
    return _begin + (_end - _begin) * _curve.transform(t);
  }

  
  double dx(double timeInSeconds) {
    final double t = clampDouble(timeInSeconds / _durationInSeconds, 0.0, 1.0);
    if (t == 0.0 || t == 1.0)
      return 0.0;
    return (_end - _begin) * _curve.derivativeAt(t) / _durationInSeconds;
  }

  
  bool isDone(double timeInSeconds) => timeInSeconds >= _durationInSeconds;
}

SpringSimulation源码:

// packages/flutter/lib/src/physics/spring_simulation.dart
class SpringSimulation extends Simulation {
  SpringSimulation(
    SpringDescription spring,
    double start,
    double end,
    double velocity, {
    Tolerance tolerance = Tolerance.defaultTolerance,
  }) : _spring = spring,
       _solution = _SpringSolution(spring, start - end, velocity),
       _type = _SpringType.underDamped,
       _endPosition = end,
       super(tolerance: tolerance) {
    // ...
  }

  final SpringDescription _spring;
  final _SpringSolution _solution;
  final _SpringType _type;
  final double _endPosition;

  
  double x(double time) => _endPosition + _solution.position(time);

  
  double dx(double time) => _solution.velocity(time);

  
  bool isDone(double time) {
    return _solution.position(time).abs() < tolerance.distance
        && _solution.velocity(time).abs() < tolerance.velocity;
  }
}

动画状态与通知:

AnimationController实现了Animation接口,提供了状态通知机制:

// packages/flutter/lib/src/animation/animation.dart
abstract class Animation<T> extends Listenable {
  // 动画值
  T get value;

  // 动画状态
  AnimationStatus get status;

  // 添加状态监听器
  void addStatusListener(AnimationStatusListener listener);

  // 移除状态监听器
  void removeStatusListener(AnimationStatusListener listener);
}

动画控制器的使用:

// 创建动画控制器
final AnimationController controller = AnimationController(
  duration: const Duration(seconds: 2),
  vsync: this,
);

// 正向运行
controller.forward();

// 反向运行
controller.reverse();

// 动画到指定值
controller.animateTo(0.5, duration: Duration(milliseconds: 500));

// 重复动画
controller.repeat();

// 添加监听器
controller.addListener(() {
  setState(() {
    // 使用controller.value更新UI
  });
});

// 添加状态监听器
controller.addStatusListener((status) {
  if (status == AnimationStatus.completed) {
    // 动画完成时的处理
  }
});

7.3 动画插值与曲线

动画插值是将动画进度(0.0到1.0)转换为具体值的过程。Flutter提供了丰富的插值机制和曲线函数。

Tween源码:

Tween定义了起点和终点,负责将动画进度转换为具体类型的值:

// packages/flutter/lib/src/animation/tween.dart
class Tween<T extends num> extends Animatable<T> {
  // 构造函数
  Tween({ required this.begin, required this.end });

  // 起点值
  final T begin;

  // 终点值
  final T end;

  // 插值计算
  
  T transform(double t) {
    if (t == 0.0)
      return begin;
    if (t == 1.0)
      return end;
    return begin + (end - begin) * t as T;
  }

  // 获取动画对象
  Animation<T> animate(Animation<double> parent) {
    return _AnimatedEvaluation<T>(parent, this);
  }
}

ColorTween源码:

ColorTween是特定类型的Tween,用于颜色过渡:

// packages/flutter/lib/src/animation/tween.dart
class ColorTween extends Tween<Color?> {
  ColorTween({ required Color? begin, required Color? end }) : super(begin: begin, end: end);

  
  Color? transform(double t) {
    if (begin == null && end == null)
      return null;
    if (begin == null)
      return Color.lerp(begin, end, t);
    if (end == null)
      return Color.lerp(begin, end, t);
    return Color.lerp(begin, end, t);
  }
}

曲线函数(Curve)源码:

曲线函数定义了动画进度的变化方式,使动画具有不同的效果:

// packages/flutter/lib/src/animation/curves.dart
abstract class Curve {
  const Curve();

  // 转换进度值
  double transform(double t);

  // 获取在特定点的导数
  double derivativeAt(double t) {
    return (transform(t + _kGoldenRatio) - transform(t)) / _kGoldenRatio;
  }

  // 创建动画区间
  Curve get flipped => FlippedCurve(this);
}

// 线性曲线
class _Linear extends Curve {
  const _Linear._();

  
  double transform(double t) => t;
}

// 缓入曲线
class _EaseInCurve extends Curve {
  const _EaseInCurve();

  
  double transform(double t) => t * t;
}

// 缓出曲线
class _EaseOutCurve extends Curve {
  const _EaseOutCurve();

  
  double transform(double t) => t * (2.0 - t);
}

// 缓入缓出曲线
class _EaseInOutCurve extends Curve {
  const _EaseInOutCurve();

  
  double transform(double t) {
    if (t < 0.5)
      return 2.0 * t * t;
    return -1.0 + (4.0 - 2.0 * t) * t;
  }
}

预定义曲线:

Flutter预定义了许多常用曲线:

// packages/flutter/lib/src/animation/curves.dart
abstract class Curves {
  // 线性曲线
  static const Curve linear = _Linear._();

  // 缓入
  static const Curve easeIn = _EaseInCurve();

  // 缓出
  static const Curve easeOut = _EaseOutCurve();

  // 缓入缓出
  static const Curve easeInOut = _EaseInOutCurve();

  // 弹性曲线
  static const Curve elasticIn = ElasticInCurve();
  static const Curve elasticOut = ElasticOutCurve();
  static const Curve elasticInOut = ElasticInOutCurve();

  // 弹跳曲线
  static const Curve bounceIn = BounceInCurve();
  static const Curve bounceOut = BounceOutCurve();
  static const Curve bounceInOut = BounceInOutCurve();
}

CurvedAnimation源码:

CurvedAnimation将曲线应用于动画:

// packages/flutter/lib/src/animation/animations.dart
class CurvedAnimation extends Animation<double> with AnimationWithParentMixin<double> {
  // 构造函数
  CurvedAnimation({
    required this.parent,
    required this.curve,
    this.reverseCurve,
  });

  // 父动画
  final Animation<double> parent;

  // 正向曲线
  Curve curve;

  // 反向曲线
  Curve? reverseCurve;

  // 获取动画值
  
  double get value {
    final Curve activeCurve = _useForwardCurve ? curve : (reverseCurve ?? curve.flipped);

    final double t = parent.value;
    if (t == 0.0 || t == 1.0) {
      return t;
    }
    return activeCurve.transform(t);
  }

  // 当前是否使用正向曲线
  bool get _useForwardCurve {
    return parent.status != AnimationStatus.reverse
        && parent.status != AnimationStatus.dismissed;
  }
}

使用动画插值:

// 创建动画控制器
final controller = AnimationController(
  duration: const Duration(seconds: 2),
  vsync: this,
);

// 应用曲线
final Animation<double> curvedAnimation = CurvedAnimation(
  parent: controller,
  curve: Curves.easeInOut,
);

// 创建颜色动画
final Animation<Color?> colorAnimation = ColorTween(
  begin: Colors.blue,
  end: Colors.red,
).animate(curvedAnimation);

// 创建尺寸动画
final Animation<double> sizeAnimation = Tween<double>(
  begin: 50.0,
  end: 200.0,
).animate(curvedAnimation);

// 使用动画值
Container(
  width: sizeAnimation.value,
  height: sizeAnimation.value,
  color: colorAnimation.value,
)

自定义插值:

可以创建自定义Tween实现特殊插值:

class MyCustomTween extends Tween<MyCustomObject> {
  MyCustomTween({ required MyCustomObject begin, required MyCustomObject end })
    : super(begin: begin, end: end);

  
  MyCustomObject transform(double t) {
    return MyCustomObject(
      size: begin.size + (end.size - begin.size) * t,
      color: Color.lerp(begin.color, end.color, t),
      rotation: begin.rotation + (end.rotation - begin.rotation) * t,
    );
  }
}

自定义曲线:

可以创建自定义曲线实现特殊动画效果:

class BackAndForthCurve extends Curve {
  
  double transform(double t) {
    if (t < 0.5) {
      return t * 2.0; // 0.0 到 1.0
    } else {
      return 2.0 - t * 2.0; // 1.0 到 0.0
    }
  }
}

通过这些核心机制,Flutter的动画系统可以实现各种复杂的动画效果,同时保持高性能和流畅度。动画系统的模块化设计也使开发者可以轻松扩展和自定义动画行为。

8. 应用启动与渲染流程

8.1 引擎初始化过程

Flutter的引擎初始化是一个复杂的过程,涉及到多个系统的配置和启动。

Flutter引擎初始化流程:

  1. 平台特定入口点:

    • Android: FlutterActivityFlutterFragment
    • iOS: FlutterViewController
  2. 创建引擎实例:

    // engine/src/flutter/shell/common/shell.cc
    std::unique_ptr<Shell> Shell::Create(
        TaskRunners task_runners,
        Settings settings,
        Shell::CreateCallback on_create_platform_view,
        Shell::CreateCallback on_create_rasterizer) {
      // 创建DartVM
      auto vm = DartVMRef::Create(settings);
    
      // 创建Shell实例
      auto shell = std::unique_ptr<Shell>(new Shell(std::move(vm),
                                                std::move(task_runners),
                                                settings));
    
      // 创建平台视图
      shell->CreatePlatformView(on_create_platform_view);
    
      // 创建光栅器
      shell->CreateRasterizer(on_create_rasterizer);
    
      return shell;
    }
    
  3. 初始化Dart虚拟机:

    // engine/src/flutter/runtime/dart_vm.cc
    DartVM::DartVM(std::shared_ptr<const DartVMData> vm_data)
        : vm_data_(std::move(vm_data)) {
      // 配置Dart VM选项
      std::vector<const char*> args;
      for (const auto& arg : vm_data_->settings().dart_flags) {
        args.push_back(arg.c_str());
      }
    
      // 初始化Dart VM
      char* error = Dart_Initialize(
          vm_data_->settings().vm_snapshot_data->GetMapping(),
          vm_data_->settings().isolate_snapshot_data
              ? vm_data_->settings().isolate_snapshot_data->GetMapping()
              : nullptr,
          DartVMFlags::FlagsToDartFlags(args).data(),
          args.size(),
          nullptr,
          nullptr,
          nullptr,
          nullptr,
          nullptr);
    }
    
  4. 初始化渲染系统:

    // engine/src/flutter/shell/common/rasterizer.cc
    Rasterizer::Rasterizer(TaskRunners task_runners)
        : task_runners_(std::move(task_runners)),
          weak_factory_(this) {
      // 初始化合成上下文
      compositor_context_ = std::make_unique<CompositorContext>();
    }
    
  5. 设置平台消息通道:

    // engine/src/flutter/shell/platform/android/platform_view_android.cc
    void PlatformViewAndroid::RegisterWithJava(
        JNIEnv* env,
        jclass clazz,
        jmethodID on_platform_message_method) {
      // 注册Java回调
      on_platform_message_method_ = on_platform_message_method;
    
      // 设置平台消息处理程序
      SetupPlatformMessageHandlers();
    }
    

8.2 平台通道与插件系统

Flutter通过平台通道(Platform Channels)与原生平台通信,这是Flutter插件系统的基础。

平台通道类型:

  1. MethodChannel: 用于方法调用
  2. EventChannel: 用于事件流
  3. BasicMessageChannel: 用于基本消息传递

平台通道的实现:

// packages/flutter/lib/src/services/platform_channel.dart
class MethodChannel {
  /// 构造函数
  const MethodChannel(this.name, [this.codec = const StandardMethodCodec()]);

  /// 通道名称
  final String name;

  /// 编解码器
  final MethodCodec codec;

  /// 调用平台方法
  Future<T?> invokeMethod<T>(String method, [dynamic arguments]) async {
    final ByteData? result = await ServicesBinding.instance!.defaultBinaryMessenger
        .send(name, codec.encodeMethodCall(MethodCall(method, arguments)));
    if (result == null) {
      return null;
    }
    return codec.decodeEnvelope(result) as T?;
  }
}

消息传递过程:

// packages/flutter/lib/src/services/binding.dart

Future<ByteData?> send(String channel, ByteData? message) {
  final Completer<ByteData?> completer = Completer<ByteData?>();
  ui.PlatformDispatcher.instance.sendPlatformMessage(
    channel,
    message,
    (ByteData? reply) {
      try {
        completer.complete(reply);
      } catch (exception, stack) {
        FlutterError.reportError(FlutterErrorDetails(
          exception: exception,
          stack: stack,
          library: 'services library',
          context: ErrorDescription('during a platform message response callback'),
        ));
      }
    },
  );
  return completer.future;
}

平台插件注册与使用:

// 在Dart中使用平台插件
import 'package:camera/camera.dart';

void main() async {
  // 确保Flutter初始化完成
  WidgetsFlutterBinding.ensureInitialized();

  // 获取可用相机列表
  final cameras = await availableCameras();

  // 使用第一个相机
  final camera = cameras.first;

  runApp(MyApp(camera: camera));
}

在平台端,插件需要实现对应的原生代码:

// Android端插件实现
public class CameraPlugin implements MethodCallHandler {
  private final Activity activity;

  CameraPlugin(Activity activity) {
    this.activity = activity;
  }

  // 插件注册方法
  public static void registerWith(Registrar registrar) {
    final MethodChannel channel = new MethodChannel(registrar.messenger(), "plugins.flutter.io/camera");
    channel.setMethodCallHandler(new CameraPlugin(registrar.activity()));
  }

  // 处理方法调用
  @Override
  public void onMethodCall(MethodCall call, Result result) {
    if (call.method.equals("availableCameras")) {
      try {
        result.success(getAvailableCameras());
      } catch (Exception e) {
        result.error("cameraError", e.getMessage(), null);
      }
    } else {
      result.notImplemented();
    }
  }
}

平台通道的底层实现:

Flutter引擎中,平台通道是通过PlatformMessageChannel实现的:

// engine/src/flutter/shell/common/shell.cc
void Shell::OnPlatformViewDispatchPlatformMessage(
    std::unique_ptr<PlatformMessage> message) {
  FML_DCHECK(is_setup_);
  FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());

  if (message->response()) {
    // 如果有回调,先记录
    fml::RefPtr<PlatformMessageResponse> response = message->response();

    // 将平台消息转发给引擎
    task_runners_.GetUITaskRunner()->PostTask(
        [engine = engine_->GetWeakPtr(), message = std::move(message)]() {
          if (engine) {
            engine->DispatchPlatformMessage(std::move(message));
          }
        });
  } else {
    // 没有回调,直接转发
    task_runners_.GetUITaskRunner()->PostTask(
        [engine = engine_->GetWeakPtr(), message = std::move(message)]() {
          if (engine) {
            engine->DispatchPlatformMessage(std::move(message));
          }
        });
  }
}

插件的注册机制:

Flutter在应用启动时会自动注册插件:

// packages/flutter/lib/src/widgets/binding.dart
mixin WidgetsBinding on BindingBase, ServicesBinding, SchedulerBinding,
    GestureBinding, RendererBinding, SemanticsBinding {
  
  void initInstances() {
    super.initInstances();
    _instance = this;

    // 确保Flutter插件已注册
    _registerPluginCallbacks();
  }

  void _registerPluginCallbacks() {
    // 在平台上查找已注册的插件
    ui.PlatformDispatcher.instance.sendPlatformMessage(
      'flutter/plugin_registry',
      null,
      (ByteData? data) {
        // 处理插件注册结果
      },
    );
  }
}

事件通道的实现:

// packages/flutter/lib/src/services/platform_channel.dart
class EventChannel {
  const EventChannel(this.name, [this.codec = const StandardMethodCodec()]);

  final String name;
  final MethodCodec codec;

  Stream<dynamic> receiveBroadcastStream([dynamic arguments]) {
    final MethodChannel methodChannel = MethodChannel(name, codec);
    late StreamController<dynamic> controller;

    controller = StreamController<dynamic>.broadcast(onListen: () async {
      ServicesBinding.instance!.defaultBinaryMessenger.setMessageHandler(
        name,
        (ByteData? reply) async {
          if (reply == null) {
            controller.close();
          } else {
            try {
              controller.add(codec.decodeEnvelope(reply));
            } catch (e) {
              controller.addError(e);
            }
          }
          return null;
        }
      );

      try {
        await methodChannel.invokeMethod<void>('listen', arguments);
      } catch (exception, stack) {
        FlutterError.reportError(FlutterErrorDetails(
          exception: exception,
          stack: stack,
          library: 'services library',
          context: ErrorDescription('while activating platform stream on channel $name'),
        ));
      }
    }, onCancel: () async {
      ServicesBinding.instance!.defaultBinaryMessenger.setMessageHandler(name, null);
      try {
        await methodChannel.invokeMethod<void>('cancel', arguments);
      } catch (exception, stack) {
        FlutterError.reportError(FlutterErrorDetails(
          exception: exception,
          stack: stack,
          library: 'services library',
          context: ErrorDescription('while de-activating platform stream on channel $name'),
        ));
      }
    });

    return controller.stream;
  }
}

通过平台通道和插件系统,Flutter实现了与原生平台的无缝集成,使开发者能够充分利用平台特定功能。

8.3 首帧渲染全链路分析

Flutter应用的首帧渲染是一个复杂的过程,涉及多个子系统的协同工作。下面是Flutter应用从启动到首帧渲染的完整调用链路分析。

Flutter应用启动和首帧渲染调用链路图:

runApp(MyApp())
│
├── WidgetsFlutterBinding.ensureInitialized()    # 确保绑定初始化
│   ├── BindingBase()                           # 基础绑定
│   ├── ServicesBinding()                       # 服务绑定
│   ├── SchedulerBinding()                      # 调度绑定
│   ├── GestureBinding()                        # 手势绑定
│   ├── RendererBinding()                       # 渲染绑定
│   └── WidgetsBinding()                        # Widget绑定
│
├── WidgetsBinding.scheduleAttachRootWidget()   # 调度附加根Widget
│   └── Timer.run(() => attachRootWidget())     # 下一帧开始前执行
│
├── WidgetsBinding.attachRootWidget()           # 附加根Widget
│   └── RenderObjectToWidgetAdapter.attachToRenderTree()  # 创建Element树
│       ├── createElement()                     # 创建RenderObjectToWidgetElement
│       └── mount()                             # 挂载Element
│           ├── assignOwner()                   # 分配BuildOwner
│           ├── _rebuild()                      # 重建Element
│           │   └── performRebuild()            # 执行重建
│           │       ├── child = updateChild()   # 更新子Element
│           │       └── widget.createRenderObject()  # 创建RenderObject
│           └── attachRenderObject()            # 附加RenderObject到父级
│
├── WidgetsBinding.scheduleWarmUpFrame()        # 调度预热帧
│   └── Timer.run(() => {                       # 下一帧开始前执行
│       ├── handleBeginFrame()                  # 处理帧开始
│       │   ├── SchedulerBinding.handleBeginFrame()  # 调度绑定处理帧开始
│       │   └── SchedulerPhase.idle -> persistent -> postFrameCallbacks  # 执行各阶段回调
│       │
│       └── handleDrawFrame()                   # 处理帧绘制
│           ├── WidgetsBinding.drawFrame()      # Widget绑定绘制帧
│           │   ├── buildOwner.buildScope()     # 构建Widget树
│           │   │   └── Element.rebuild()       # 重建Element
│           │   │       └── Element.performRebuild()  # 执行重建
│           │   │           └── build()         # 构建Widget
│           │   └── buildOwner.finalizeTree()   # 完成树构建
│           │
│           ├── RendererBinding.drawFrame()     # 渲染绑定绘制帧
│           │   ├── pipelineOwner.flushLayout() # 刷新布局
│           │   │   └── RenderObject.performLayout()  # 执行布局
│           │   │       └── RenderObject.layout()     # 布局子元素
│           │   │
│           │   ├── pipelineOwner.flushCompositingBits()  # 刷新合成位
│           │   │   └── RenderObject._updateCompositingBits()  # 更新合成位
│           │   │
│           │   ├── pipelineOwner.flushPaint()  # 刷新绘制
│           │   │   └── RenderObject.paint()    # 执行绘制
│           │   │       └── RenderObject._paintWithContext()  # 使用上下文绘制
│           │   │           └── PaintingContext.canvas.drawXXX()  # 绘制到画布
│           │   │
│           │   └── renderView.compositeFrame() # 合成帧
│           │       ├── ui.SceneBuilder()       # 创建场景构建器
│           │       ├── layer.buildScene()      # 构建场景
│           │       │   └── Layer.addToScene()  # 添加图层到场景
│           │       │       └── ui.SceneBuilder.addXXX()  # 添加图层操作
│           │       └── ui.Window.render()      # 渲染场景
│           │           └── [C++] Dart_InvokeVMServiceMethod("Render")  # 调用VM服务
│           │               └── [C++] RuntimeController::Render()  # 运行时控制器渲染
│           │                   └── [C++] Shell::OnAnimatorDraw()  # Shell绘制
│           │                       └── [C++] Rasterizer::DrawToSurface()  # 光栅器绘制
│           │                           ├── [C++] LayerTree::Preroll()  # 图层树预处理
│           │                           ├── [C++] LayerTree::Paint()    # 图层树绘制
│           │                           └── [C++] 提交到GPU              # 提交到GPU
│           │
│           └── _firstFrameCompleted = true    # 标记首帧完成
│
└── Flutter应用显示在屏幕上                       # 首帧渲染完成

首帧渲染过程的源码分析:

1. 启动入口 - runApp():

// packages/flutter/lib/src/widgets/binding.dart
void runApp(Widget app) {
  // 确保Flutter绑定初始化
  WidgetsFlutterBinding.ensureInitialized()
    // 调度附加根Widget
    ..scheduleAttachRootWidget(app)
    // 调度预热帧
    ..scheduleWarmUpFrame();
}

2. 绑定初始化 - WidgetsFlutterBinding.ensureInitialized():

// packages/flutter/lib/src/widgets/binding.dart
static WidgetsBinding ensureInitialized() {
  if (_instance == null)
    WidgetsFlutterBinding();
  return _instance!;
}

// WidgetsFlutterBinding混合了多个绑定
class WidgetsFlutterBinding extends BindingBase with GestureBinding, ServicesBinding, SchedulerBinding, PaintingBinding, SemanticsBinding, RendererBinding, WidgetsBinding {
  // 构造函数会调用所有mixin的initInstances方法
  WidgetsFlutterBinding() {
    initInstances();
  }
}

3. 附加根Widget - scheduleAttachRootWidget():

// packages/flutter/lib/src/widgets/binding.dart
void scheduleAttachRootWidget(Widget rootWidget) {
  Timer.run(() {
    attachRootWidget(rootWidget);
  });
}

void attachRootWidget(Widget rootWidget) {
  // 创建RenderObjectToWidgetAdapter,它是RootWidget和RenderView之间的桥梁
  _renderViewElement = RenderObjectToWidgetAdapter<RenderBox>(
    container: renderView,
    debugShortDescription: '[root]',
    child: rootWidget,
  ).attachToRenderTree(buildOwner, renderViewElement);
}

4. 调度预热帧 - scheduleWarmUpFrame():

// packages/flutter/lib/src/scheduler/binding.dart
void scheduleWarmUpFrame() {
  if (_warmUpFrame || schedulerPhase != SchedulerPhase.idle)
    return;

  _warmUpFrame = true;
  final bool hadScheduledFrame = _hasScheduledFrame;
  // 一些模拟器不会自动发送初始VSync信号
  // 所以我们手动请求一帧
  Timer.run(() {
    handleBeginFrame(null);
    handleDrawFrame();
    resetEpoch();
    _warmUpFrame = false;
    if (hadScheduledFrame)
      scheduleFrame();
  });
}

5. 处理帧 - handleBeginFrame() 和 handleDrawFrame():

// packages/flutter/lib/src/scheduler/binding.dart
void handleBeginFrame(Duration? rawTimeStamp) {
  Timeline.startSync('Frame', arguments: timelineWhitelistArguments);
  _firstRawTimeStampInEpoch ??= rawTimeStamp;
  _currentFrameTimeStamp = _adjustForEpoch(rawTimeStamp ?? _lastRawTimeStamp);

  // 如果有动画和帧回调,执行它们
  if (schedulerPhase == SchedulerPhase.idle) {
  _schedulerPhase = SchedulerPhase.transientCallbacks;
    try {
      _invokeTransientFrameCallbacks(_currentFrameTimeStamp!);
    } finally {
  _schedulerPhase = SchedulerPhase.midFrameMicrotasks;
    }
  }
}

void handleDrawFrame() {
  assert(_schedulerPhase == SchedulerPhase.midFrameMicrotasks);
  Timeline.finishSync(); // 结束"Frame"部分

  try {
    // 持久帧回调阶段
  _schedulerPhase = SchedulerPhase.persistentCallbacks;
    _invokeFrameCallbacks(_FrameCallbackPhase.persistentCallbacks, _currentFrameTimeStamp!);

    // 帧后回调阶段
  _schedulerPhase = SchedulerPhase.postFrameCallbacks;
    _invokeFrameCallbacks(_FrameCallbackPhase.postFrameCallbacks, _currentFrameTimeStamp!);
  } finally {
  _schedulerPhase = SchedulerPhase.idle;
  }
}

6. Widget绑定绘制帧 - WidgetsBinding.drawFrame():

// packages/flutter/lib/src/widgets/binding.dart

void drawFrame() {
  try {
    if (renderViewElement != null)
      buildOwner!.buildScope(renderViewElement!);
    super.drawFrame();
    buildOwner!.finalizeTree();
  } finally {
    // ...
  }
}

7. 渲染绑定绘制帧 - RendererBinding.drawFrame():

// packages/flutter/lib/src/rendering/binding.dart

void drawFrame() {
  assert(renderView != null);
  pipelineOwner.flushLayout();
  pipelineOwner.flushCompositingBits();
  pipelineOwner.flushPaint();
  renderView.compositeFrame(); // 合成帧
  pipelineOwner.flushSemantics(); // 确保语义可用
}

8. 合成帧 - RenderView.compositeFrame():

// packages/flutter/lib/src/rendering/view.dart
void compositeFrame() {
  if (!kReleaseMode) {
    Timeline.startSync('Compositing', arguments: timelineWhitelistArguments);
  }
  try {
    // 创建场景构建器
    final ui.SceneBuilder builder = ui.SceneBuilder();
    // 构建场景
    final ui.Scene scene = layer!.buildScene(builder);
    // 渲染场景
    window.render(scene);
    // 释放场景资源
    scene.dispose();
  } finally {
    if (!kReleaseMode) {
      Timeline.finishSync();
    }
  }
}

9. Flutter引擎渲染 - C++部分:

在Dart调用window.render(scene)后,控制权传递给C++层:

// engine/src/flutter/lib/ui/window/window.cc
void Window::Render(Dart_NativeArguments args) {
  // 获取Scene参数
  Scene* scene = tonic::DartConverter<Scene*>::FromArguments(args, 0);

  // 获取当前的Shell
  UIDartState* dart_state = UIDartState::Current();
  std::shared_ptr<tonic::DartState> dart_state_ptr = dart_state->GetWeakPtr();

  // 在平台线程上执行渲染
  fml::TaskRunner::RunNowOrPostTask(
      dart_state->GetTaskRunners().GetPlatformTaskRunner(),
      [engine = dart_state->GetEngine(), scene_ptr = scene->scene(),
       dart_state_ptr]() {
        if (!dart_state_ptr)
          return;
        // 引擎渲染场景
        engine->GetShell().GetPlatformView()->RenderScene(scene_ptr);
      });
}

10. Shell和Rasterizer渲染 - C++部分:

// engine/src/flutter/shell/common/rasterizer.cc
void Rasterizer::DrawToSurface(FramePipeline::FrameResult& frame) {
  // 获取Surface
  auto surface = surface_producer_->ProduceSurface(frame.GetFrameSize());

  if (!surface) {
    return;
  }

  // 获取Canvas和GrContext
  auto canvas = surface->getCanvas();
  auto gr_context = surface_producer_->GetContext();

  // 创建合成上下文
  CompositorContext::ScopedFrame compositor_frame =
      compositor_context_.AcquireFrame(gr_context, canvas, nullptr,
                                     surface_producer_->GetRootTransformation());

  // 预处理图层树
  frame.GetLayerTree().Preroll(compositor_frame);

  // 绘制图层树
  frame.GetLayerTree().Paint(compositor_frame);

  // 提交Surface
  surface_producer_->PresentSurface(std::move(surface));
}

首帧渲染流程总结:

  1. 初始化阶段:

    • 创建并初始化各种绑定(Binding)
    • 注册服务和回调
  2. 构建阶段:

    • 创建Widget树
    • 创建/更新Element树
    • 创建/更新RenderObject树
  3. 布局阶段:

    • 从上到下传递约束
    • 从下到上计算尺寸
  4. 绘制阶段:

    • 创建图层树
    • 记录绘制命令
  5. 合成阶段:

    • 将图层树转换为场景
    • 提交场景到Flutter引擎
  6. 光栅化阶段:

    • 预处理图层树
    • 光栅化绘制命令
    • 生成纹理
  7. 渲染阶段:

    • 提交到GPU
    • 显示到屏幕

首帧渲染完成后,Flutter应用进入正常的渲染循环,通过VSync信号驱动后续帧的渲染。

9. 性能优化原理

Flutter框架设计了多种性能优化机制,确保应用流畅运行。本节深入分析Flutter的性能优化原理。

9.1 重建优化策略

Flutter的UI更新采用增量重建策略,只更新需要变化的部分,从而提高性能。

Element重建优化:

Element树的重建是Flutter性能优化的关键环节:

// packages/flutter/lib/src/widgets/framework.dart
void buildScope(Element context, [VoidCallback? callback]) {
  if (callback != null) {
    Timeline.startSync('Build', arguments: timelineWhitelistArguments);
    try {
      callback();
    } finally {
      Timeline.finishSync();
    }
  }

  // 排序脏元素(按深度升序)
  _dirtyElements.sort(Element._sort);

  // 仅重建脏元素
  int dirtyCount = _dirtyElements.length;
  int index = 0;
  while (index < dirtyCount) {
    final Element element = _dirtyElements[index];
    if (element._dirty && element.active) {
      element.rebuild();
    }
    index += 1;
  }

  // 清空脏元素列表
  _dirtyElements.clear();
}

shouldRepaint机制:

CustomPainter使用shouldRepaint减少不必要的重绘:

// packages/flutter/lib/src/rendering/custom_paint.dart

void paint(PaintingContext context, Offset offset) {
  // 只有当前绘制器与上一个不同,且shouldRepaint返回true时才重绘
  _didChangeSignature = !identical(_painter, _previousPainter) && (_previousPainter == null || _painter == null || _painter!.shouldRepaint(_previousPainter!));

  if (_didChangeSignature)
    context.canvas.save();

  if (_didChangeSignature && erasePaint != null)
    context.canvas.drawPaint(erasePaint!);

  if (_painter != null)
    _painter!._paint(context.canvas, size);

  if (_didChangeSignature)
    context.canvas.restore();
}

const构造函数优化:

使用const构造函数创建的Widget可以在编译时确定身份,避免不必要的重建:

// 示例: const构造函数优化
class MyWidget extends StatelessWidget {
  // 使用const构造函数
  const MyWidget({Key? key, required this.title}) : super(key: key);

  final String title;

  
  Widget build(BuildContext context) {
    // 子Widget使用const构造,当MyWidget重建时,
    // 这些子Widget不会创建新实例
    return Container(
      padding: const EdgeInsets.all(8.0),
      color: const Color(0xFFEEEEEE),
      child: const Icon(Icons.star),
    );
  }
}

StatefulWidget优化:

StatefulWidget的shouldUpdate可以控制是否需要更新:

// packages/flutter/lib/src/widgets/framework.dart
void update(StatefulWidget newWidget) {
  final StatefulWidget oldWidget = widget as StatefulWidget;
  super.update(newWidget);
  final State state = this.state;

  // 更新state的widget引用
  state._widget = newWidget;

  // 只有当shouldUpdateWidget返回true时才调用didUpdateWidget
  if (oldWidget != newWidget && state.shouldUpdateWidget(oldWidget)) {
    state.didUpdateWidget(oldWidget);
  }

  state.reassemble();
}

9.2 渲染优化技术

Flutter的渲染系统包含多种优化技术,提高渲染性能。

RepaintBoundary隔离重绘区域:

RepaintBoundary创建独立的图层,防止重绘扩散:

// packages/flutter/lib/src/widgets/basic.dart
class RepaintBoundary extends SingleChildRenderObjectWidget {
  const RepaintBoundary({Key? key, Widget? child}) : super(key: key, child: child);

  
  RenderRepaintBoundary createRenderObject(BuildContext context) => RenderRepaintBoundary();
}

// packages/flutter/lib/src/rendering/proxy_box.dart
class RenderRepaintBoundary extends RenderProxyBox {
  
  bool get isRepaintBoundary => true;

  
  void paint(PaintingContext context, Offset offset) {
    // 创建新的离屏图层
    context.pushLayer(OffsetLayer(), super.paint, offset);
  }
}

渲染缓存机制:

Flutter引擎中的RasterCache缓存已绘制的图层:

// engine/src/flutter/flow/raster_cache.cc
sk_sp<SkImage> RasterCache::GetPrerolledImage(
    GrDirectContext* context,
    SkPicture* picture,
    const SkMatrix& ctm,
    SkColorSpace* dst_color_space,
    bool is_complex,
    bool will_change) {
  // 检查是否应该缓存
  if (!ShouldBeCached(picture->uniqueID(), is_complex, will_change)) {
    return nullptr;
  }

  // 查找缓存
  auto it = cache_.find(picture->uniqueID());
  if (it == cache_.end()) {
    return nullptr;
  }

  Entry& entry = it->second;
  if (entry.access_count < access_threshold_) {
    // 增加访问计数
    entry.access_count++;
    return nullptr;
  }

  // 检查是否需要重新渲染
  if (entry.image == nullptr) {
    entry.image = RasterizePicture(context, picture, ctm, dst_color_space);
  }

  return entry.image;
}

分层渲染:

Flutter使用分层渲染系统,只更新变化的图层:

// packages/flutter/lib/src/rendering/layer.dart
class ContainerLayer extends Layer {
  
  void addToScene(ui.SceneBuilder builder, [Offset layerOffset = Offset.zero]) {
    addChildrenToScene(builder, layerOffset);
  }

  void addChildrenToScene(ui.SceneBuilder builder, [Offset childOffset = Offset.zero]) {
    // 只添加需要更新的子层
    for (Layer child in _children!) {
      if (child._needsAddToScene) {
        child.addToScene(builder, childOffset);
      }
    }
  }
}

Skia快速路径:

Flutter利用Skia的快速路径优化常见绘制操作:

// engine/src/third_party/skia/src/core/SkCanvas.cpp
void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
  // 检查是否可以使用快速路径
  if (paint.canComputeFastBounds()) {
    SkRect storage;
    if (this->quickReject(paint.computeFastBounds(r, &storage))) {
      return;
    }
  }

  // 使用快速路径绘制矩形
  this->onDrawRect(r, paint);
}

9.3 内存管理与优化

Flutter的内存管理包括Dart垃圾回收和原生资源管理。

Dart内存管理:

Flutter使用Dart VM的垃圾回收机制管理内存:

// Dart内存管理示例
void memoryManagementExample() {
  // 创建局部变量
  var list = List.generate(10000, (i) => i);

  // 离开作用域后,list会被垃圾回收
  print('List created');

  // 主动触发垃圾回收(仅用于演示,实际应用中不应该这样做)
  // ignore: invalid_use_of_visible_for_testing_member
  // ignore: invalid_use_of_protected_member
  // HeapProfiling.collectAllGarbage();
}

图像缓存管理:

Flutter的ImageCache控制图像内存使用:

// packages/flutter/lib/src/painting/image_cache.dart
class ImageCache {
  // 默认最大图像数量
  static const int _kDefaultSize = 1000;
  // 默认最大内存使用量(字节)
  static const int _kDefaultSizeBytes = 100 << 20; // 100 MiB

  // 当前缓存的图像数量
  int get currentSize => _cache.length;

  // 当前内存使用量
  int get currentSizeBytes => _currentSizeBytes;

  // 清除缓存
  void clear() {
    _cache.clear();
    _liveImages.clear();
    _pendingImages.clear();
    _currentSizeBytes = 0;
  }

  // 缓存图像
  void putIfAbsent(Object key, ImageStreamCompleter Function() loader) {
    // 检查是否已在缓存中
    final _CachedImage? image = _cache.remove(key);
    if (image != null) {
      _cache[key] = image;
      return image.completer;
    }

    // 检查是否有足够空间
    final int imageSize = _pendingImages[key]?.second ?? 0;
    if (maximumSize > 0 && _cache.length + 1 > maximumSize) {
      _checkCacheSize(imageSize);
    }

    // 加载并缓存图像
    final ImageStreamCompleter completer = loader();
    _pendingImages[key] = Pair<ImageStreamCompleter, int>(completer, imageSize);

    return completer;
  }
}

资源释放机制:

Flutter确保资源在不再需要时释放:

// packages/flutter/lib/src/widgets/image.dart

void dispose() {
  _imageStream?.removeListener(ImageStreamListener(_handleImageFrame));
  _imageStream = null;
  super.dispose();
}

内存泄漏防护:

Flutter提供了工具帮助检测和防止内存泄漏:

// packages/flutter/lib/src/widgets/binding.dart
void addObserver(WidgetsBindingObserver observer) {
  _observers.add(observer);
}

void removeObserver(WidgetsBindingObserver observer) {
  _observers.remove(observer);
}

正确实现dispose方法防止内存泄漏:

class MyWidget extends StatefulWidget {
  
  _MyWidgetState createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  // 可能占用资源的控制器
  late AnimationController _controller;
  late StreamSubscription _subscription;

  
  void initState() {
    super.initState();
    _controller = AnimationController(vsync: this);
    _subscription = someStream.listen((_) {});
  }

  
  void dispose() {
    // 释放资源
    _controller.dispose();
    _subscription.cancel();
    super.dispose();
  }

  
  Widget build(BuildContext context) {
    return Container();
  }
}

通过这些优化技术,Flutter可以在各种设备上提供流畅的用户体验。理解这些优化原理有助于开发者创建高性能的Flutter应用。

Logo

GitCode 天启AI是一款由 GitCode 团队打造的智能助手,基于先进的LLM(大语言模型)与多智能体 Agent 技术构建,致力于为用户提供高效、智能、多模态的创作与开发支持。它不仅支持自然语言对话,还具备处理文件、生成 PPT、撰写分析报告、开发 Web 应用等多项能力,真正做到“一句话,让 Al帮你完成复杂任务”。

更多推荐