美文网首页
2023-03-29 flutter widget 更新9

2023-03-29 flutter widget 更新9

作者: 我是小胡胡分胡 | 来源:发表于2023-03-29 10:51 被阅读0次

    markNeedsBuild()方法是通知Flutter引擎需要重新构建widget树,而Flutter引擎会在Native层发送命令,通知Native层需要刷新Flutter视图。Native层收到命令后,会调用Flutter引擎提供的接口来刷新Flutter视图,并将新的Flutter视图与Native视图合并后显示在屏幕上。

    1、flutter标记需要刷新-》flutter 通知native刷新-〉native调用flutter刷新

    setState(() { });

     void setState(VoidCallback fn) {
        assert(fn != null);
        
        final Oject? result = fn() as dynamic;
      
        _element!.markNeedsBuild();
      }
    

    _element!.markNeedsBuild();

     void markNeedsBuild() {
        assert(_lifecycleState != _ElementLifecycle.defunct);
        if (_lifecycleState != _ElementLifecycle.active)
          return;
        assert(owner != null);
        assert(_lifecycleState == _ElementLifecycle.active);
        
        if (dirty)
          return;
        _dirty = true;
        owner!.scheduleBuildFor(this);
      }
    

    owner!.scheduleBuildFor(this);

    onBuildScheduled!();
    _dirtyElements.add(element);

     void scheduleBuildFor(Element element) {
        assert(element != null);
        assert(element.owner == this);
         
        if (element._inDirtyList) {
        
          _dirtyElementsNeedsResorting = true;
          return;
        }
        if (!_scheduledFlushDirtyElements && onBuildScheduled != null) {
          _scheduledFlushDirtyElements = true;
          onBuildScheduled!();
        }
        _dirtyElements.add(element);
        element._inDirtyList = true;
     
      }
    

    onBuildScheduled!();

    
     void scheduleFrame() {
        if (_hasScheduledFrame || !framesEnabled)
          return;
     
        ensureFrameCallbacksRegistered();
        platformDispatcher.scheduleFrame();
        _hasScheduledFrame = true;
      } 
    

    platformDispatcher.scheduleFrame();:

      ui.PlatformDispatcher get platformDispatcher => ui.PlatformDispatcher.instance;
    

    2、native 调用flutter 刷新

    flutter 刷新界面

    native通知到flutter,flutter回调:
    PlatformDispatcher.instance._drawFrame();

    @pragma('vm:entry-point')
    void _drawFrame() {
      PlatformDispatcher.instance._drawFrame();
    }
    

    void drawFrame()

    mixin WidgetsBinding

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

    buildOwner!.buildScope(renderViewElement!);树:

    这里面完成widget、element、renderboject 树 创建和更新。

    mixin WidgetsBinding {
        _buildOwner = BuildOwner();
    }
    class BuildOwner {
      void buildScope(Element context, [ VoidCallback? callback ]) 
    }
    

    RendererBinding drawFrame();

    super.drawFrame();

      void drawFrame() {
        assert(renderView != null);
        pipelineOwner.flushLayout(); //调用管道所有者的flushLayout方法,以刷新布局。在Flutter中,布局是指定义小部件如何排列的过程。
        pipelineOwner.flushCompositingBits(); //调用管道所有者的flushCompositingBits方法,以刷新合成位。合成是指在渲染过程中,将小部件组合成一个图像的过程。
        pipelineOwner.flushPaint(); //调用管道所有者的flushPaint方法,以刷新绘制。在Flutter中,绘制是指将小部件渲染为像素的过程。
        if (sendFramesToEngine) {
          renderView.compositeFrame(); // this sends the bits to the GPU,调用渲染视图的compositeFrame方法,将渲染帧发送到GPU
          pipelineOwner.flushSemantics(); // this also sends the semantics to the OS.用管道所有者的flushSemantics方法,将语义信息发送到操作系统。在Flutter中,语义信息用于描述小部件在用户界面中的作用。
          _firstFrameSent = true;//将_firstFrameSent变量设置为true,以表示第一帧已经发送到GPU。
        }
      }
    
    

    《Flutter实战·第二版》布局(Layout)过程 链接地址

    Layout(布局)过程主要是确定每一个组件的布局信息(大小和位置),Flutter 的布局过程如下:

    • 父节点向子节点传递约束(constraints)信息,限制子节点的最大和最小宽高。
    • 子节点根据约束信息确定自己的大小(size)。
    • 父节点根据特定布局规则(不同布局组件会有不同的布局算法)确定每一个子节点在父节点布局空间中的位置,用偏移 offset 表示。
    • 递归整个过程,确定出每一个节点的大小和位置。

    可以看到,组件的大小是由自身决定的,而组件的位置是由父组件决定的。

    相关文章

      网友评论

          本文标题:2023-03-29 flutter widget 更新9

          本文链接:https://www.haomeiwen.com/subject/anlxddtx.html