Flutter 核心原理与混合开发模式,kotlin二维数组

StatefulWidget

注:以上两图出自 《Flutter 核心技术与实战 | 陈航》

1.4.2 Layout

只有布局类 Widget 会触发 layout(如 Container、Padding、Align 等)。

每个 RenderObject 节点需要做两件事:

  1. 调用自己的 performLayout 来计算 layout

  2. 调用 child 的 layout,把 parent 的限制传入

/// 实际计算 layout 的实现void performLayout() { _size = configuration.size; if (child != null) { child.layout(BoxConstraints.tight(_size)); }}void layout(Constraints constraints, { bool parentUsesSize = false }) { /// …省略无关逻辑 RenderObject relayoutBoundary; if (!parentUsesSize || sizedByParent || constraints.isTight || parent is! RenderObject) { relayoutBoundary = this; } else { relayoutBoundary = (parent as RenderObject)._relayoutBoundary; } if (!_needsLayout && constraints == _constraints && relayoutBoundary == _relayoutBoundary) { return; } _constraints = constraints; _relayoutBoundary = relayoutBoundary; if (sizedByParent) { performResize(); } RenderObject debugPreviousActiveLayout; performLayout(); markNeedsSemanticsUpdate(); _needsLayout = false; markNeedsPaint();}

如此递归一轮,每个节点都受到父节点的约束并计算出自己的 size,然后父节点就可以按照自己的逻辑决定各个子节点的位置,从而完成整个 Layout 环节。

layout

1.4.3 Paint

渲染管道中首先找出需要重绘的 RenderObject,如果有实现了 CustomPainter 则调用 CustomPainter paint 方法 再调用 child 的 paint 方法;如果未实现 CustomPainter,则直接调用 child 的 paint。

在调用 paint 的时候,经过一串的转换后,layer->PaintingContext->Canvas,最终 paint 就是描绘在 Canvas 上。

void paint(PaintingContext context, Offset offset) { if (_painter != null) { // 只有持有 CustomPainter 情况下,才继续往下调用自定义的 CustomPainter 的 paint 方法,把 canvas 传过去 _paintWithPainter(context.canvas, offset, _painter); _setRasterCacheHints(context); } super.paint(context, offset); //调用父类的paint的方法 if (_foregroundPainter != null) { _paintWithPainter(context.canvas, offset, _foregroundPainter); _setRasterCacheHints(context); }}// 在父类的 paint 里面继续调用 child 的 paint,实现父子遍历void paint(PaintingContext context, Offset offset) { if (child != null){ context.paintChild(child, offset); }void _paintWithPainter(Canvas canvas, Offset offset, CustomPainter painter) { int debugPreviousCanvasSaveCount; canvas.save(); if (offset != Offset.zero) canvas.translate(offset.dx, offset.dy); // 在调用 paint 的时候,经过一串的转换后,layer->PaintingContext->Canvas,最终 paint 就是描绘在 Canvas 上 painter.paint(canvas, size); /// … canvas.restore();}

1.4.4 Composite

合成主要做三件事情:

  1. 把所有 Layer 组合成 Scene

  2. 通过 ui.window.render 方法,把 Scene 提交给 Engine。

  3. Engine 把计算所有的 Layer 最终的显示效果,渲染到屏幕上。

final ui.Window _window;void compositeFrame() { // 省略计时逻辑 final ui.SceneBuilder builder = ui.SceneBuilder(); final ui.Scene scene = layer.buildScene(builder); if (automaticSystemUiAdjustment) _updateSystemChrome(); _window.render(scene); scene.dispose();}void addToScene(ui.SceneBuilder builder, [ Offset layerOffset = Offset.zero ]) { addChildrenToScene(builder);}void addChildrenToScene(ui.SceneBuilder builder, [ Offset childOffset = Offset.zero ]) { Layer child = firstChild; while (child != null) { if (childOffset == Offset.zero) { child._addToSceneWithRetainedRendering(builder); } else { child.addToScene(builder, childOffset); } child = child.nextSibling; }}

2. 跨端方案对比


跨端开发是必然趋势,从本质上来说,它增加业务代码的复用率,减少因为适配不同平台带来的工作量,从而降低开发成本。在各平台差异抹平之前,要想“多快好省”地开发出各端体验接近一致的程序,那便是跨端开发了。

总得来说,业内普遍认同跨端方案存在以下三种:

  1. Web 容器方案

  2. 泛 Web 容器方案

  3. 自绘引擎方案

下面来一一讲解。

2.1 Web 容器


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部