2023-03-29 flutter widget 更新9

2023-03-29  本文已影响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 的布局过程如下:

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

上一篇下一篇

猜你喜欢

热点阅读