Flutter入门——Widget、Element和RenderObject的由来

2020-11-2209:25:56APP与小程序开发Comments2,334 views字数 2758阅读模式

Flutter入门——Widget、Element和RenderObject的由来文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/20728.html

可能由于这些文章的切入点不同(或本人愚钝),我在初学(甚至入门一段时间后)flutter时,并不能透彻理解这三棵树的作用到底是什么,大概最大的用处就是应付面试官了......文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/20728.html

在一段时间的学习之后,我将自身对这三个类的理解(最基本的职责)在下文概括出来,希望对你在深入理解Widget、Element和RenderObject时有所帮助。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/20728.html

Widget、Element和RenderObject

纯属个人愚见,如有错误还请指出,谢谢。
复制代码

Widget

远古时期,古人们要想通过Flutter造一个( 100*100 )蓝色方块,需要通过如下操作:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/20728.html

来自 :https://juejin.cn/post/6844904104452440072  
		作者:恋猫de小郭

import 'dart:ui' as ui;

void main() {
  ui.window.onBeginFrame = beginFrame;

  ui.window.scheduleFrame();
}

void beginFrame(Duration timeStamp) {
  final double devicePixelRatio = ui.window.devicePixelRatio;

  ///创建一个画板、录制绘制指令
  final ui.PictureRecorder recorder = ui.PictureRecorder();

  ///基于画板创建一个 Canvas
  final ui.Canvas canvas = ui.Canvas(recorder);
  canvas.scale(devicePixelRatio, devicePixelRatio);
  
  //布局
  var centerX = ui.window.physicalSize.width / 2.0;
  var centerY = ui.window.physicalSize.height / 2.0;
  
  ///画一个 100 的剧中蓝色
  Paint blueP = new Paint()..color = Colors.blue;
  
  canvas.drawLine(Offset.zero,Offset(100,0),blueP);
  canvas.drawLine(Offset(100,0),Offset(100,100),blueP);
  canvas.drawLine(Offset(100,100),Offset(0,100),blueP);
  

  ///停止录制绘制指令
  final ui.Picture picture = recorder.endRecording();
  
  //布局
  final ui.SceneBuilder sceneBuilder = ui.SceneBuilder()
    ..pushOffset(centerX, centerY)
    ..addPicture(ui.Offset.zero, picture)
    ..pop();

  ui.window.render(sceneBuilder.build());
}

复制代码

在上述一些列操作后,‘蓝色方块’便诞生了:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/20728.html

Flutter入门——Widget、Element和RenderObject的由来文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/20728.html

在长期使用后,画方块的四行代码又被优化成:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/20728.html

 //很明显这个要比上面那4行更易读、且简便。
 //也算是初代之一的‘轮子’了。
  canvas.drawRect(
      Rect.fromCenter(
          center: Offset.zero,
          width: 100,
          height: 100),
          blueP);
复制代码

又经过漫长的时间,随着轮子不断迭代,最终演变成了下面的样子:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/20728.html

	Container(
    color:Colors.blue
    width:100,height:100)
复制代码

这也就是我们Widget的由来。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/20728.html

Element

借着widget(轮子)的便捷,我只用了一天的功夫,就创建了一个绚丽页面:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/20728.html

Flutter入门——Widget、Element和RenderObject的由来文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/20728.html

它还能交互:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/20728.html

点击 圆的时候,两个圆颜色互换
点击 方块时,黄色变成了白色
点击 三角时,三角就消失了,再点击空白位置会复现。
复制代码

为了实现这个功能,我在widget里加了一大堆的标识(Flag),用来标志哪些需要更新、删除、插入等,同时添加了函数用来实现对应的功能。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/20728.html

一切完毕后,我的代码已经一团乱麻,难以阅读——可谓10分钟写代码,5分钟在滚页面......文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/20728.html

为此,element诞生了——它主要负责widget的增删改查、哪些不需要更新,哪些需要重建等等,我们看一下他的方法便一目了然。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/20728.html

....省略代码

void update(covariant Widget newWidget)

Element inflateWidget(Widget newWidget, dynamic newSlot)

void markNeedsBuild()

void performRebuild();

Element updateChild(Element child, Widget newWidget, dynamic newSlot)

....省略代码


复制代码

RenderObject

element的加入,让我的页面代码清爽了不少,同时我的页面也增加了新的酷炫功能:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/20728.html

双击页面后,会出现一个灰色矩形,盖住原来的图形,并且左右晃动。
复制代码

Flutter入门——Widget、Element和RenderObject的由来文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/20728.html

功能写完,测试机一跑,我的老爷机直接蓝屏。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/20728.html

这可不行,给老板申请资金是甭指望了,为了省钱,他还用算盘算账呢...... 只能动手优化代码了。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/20728.html

经过观察,我发现了几处可以优化的地方:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/20728.html

1, 之前的‘方块’和‘三角’被遮挡了,那么再画它们也没啥意义,布局也可以省了

2, 上面两个圆,就没动过,所以布局啊、绘制啥的都没必要再跑一遍

3, 灰色方块,大小没变,颜色也没变,我觉得只要调整它的位置就行
复制代码

先加入7、8 匙Flag,再放入10来勺函数...文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/20728.html

...一阵忙活后,在老爷机上完美运行。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/20728.html

不过我的代码又变的臃肿不堪了,只好像前面的element一样再抽出一个类来帮我管理绘制、布局、指令录制(实际封装在PaintContext)什么的了:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/20728.html

‘于是,便有了RenderObject。’
复制代码

我们可以看一下它的方法:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/20728.html

...省略代码

markNeedsLayout();
markNeedsPaint();
void performLayout();
void performResize();
void paint(PaintingContext context, Offset offset)

...省略代码

复制代码

重构

三个类添加完后,我回溯了一下他们的职责:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/20728.html

widget  方便我构建图像
element 帮我增删改查
renderObject 帮我负责布局、绘制等

同时,由于element的职能,他应该持有Widget和Renderobject
复制代码

经过一些列的设计、重构,我的页面架构最终变成了这个样子:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/20728.html

Flutter入门——Widget、Element和RenderObject的由来文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/20728.html

至此 widget、element和renderObject的基本职责就说完了,希望借由上面的文字,你能对它们三个有所初步的了解。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/20728.html

作者:吉哈达文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/20728.html

来源:掘金文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/20728.html

  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/xcx/20728.html

Comment

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定