iT邦幫忙

2022 iThome 鐵人賽

DAY 11
0
自我挑戰組

30天學習flutter系列 第 11

11.flutter的布局(四)

  • 分享至 

  • xImage
  •  

當我們將widget完全構建後,我們開始介紹如何更新布局

我們一個widget在畫面更新的流程為

1.重新構建widget
2.繪製frame

  • 2-1.更新佈局
  • 2-2.更新“layer合成”信息
  • 2-3.重新繪製widget
  • 2-4.組裝frame並將繪製後的數據發送出去來顯示在裝置屏幕上

接著我們看到布局階段

我們到flutter\packages\flutter\lib\src\widgets\binding.dart:
https://ithelp.ithome.com.tw/upload/images/20220926/20108931CApzprb7O8.png

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

在line890~893來進行widget更新顯示

並且在flutter\packages\flutter\lib\src\rendering\binding.dart:
https://ithelp.ithome.com.tw/upload/images/20220926/201089312Fi28mb110.png

  @protected
  void drawFrame() {
    assert(renderView != null);
    pipelineOwner.flushLayout();
    pipelineOwner.flushCompositingBits();
    pipelineOwner.flushPaint();
    if (sendFramesToEngine) {
      renderView.compositeFrame(); // this sends the bits to the GPU
      pipelineOwner.flushSemantics(); // this also sends the semantics to the OS.
      _firstFrameSent = true;
    }
  }

其中line504進行更新layout,line505進行更新layer合成的訊息,line506重新繪製widget,最後當sendFramesToEngine為ture時,會在line508將製後的數據發送出去給GPU

而我們的layout布局透過flushLayout實現

打開flutter\packages\flutter\lib\src\rendering\object.dart
https://ithelp.ithome.com.tw/upload/images/20220926/2010893133vOfp5USd.png

在Line884,我們把需要佈局的RederObject都加入到_nodesNeedingLayout這個list裡面

並在Line885將dirtyNodes裡的所有RenderObject,當要重新layout時,會調用_layoutWithoutResize。

_layoutWithoutResize會先執行performLayout,然後又調用了markNeedsPaint()。(一般父RenderObject在performLayout時是會調用child的layout的)

https://ithelp.ithome.com.tw/upload/images/20220926/20108931nmNyQfEB8O.png

接著就開始進行我們layout,他會計算此渲染對象的layout
flutter\packages\flutter\lib\src\rendering\object.dart
https://ithelp.ithome.com.tw/upload/images/20220926/20108931i8VDoWzpAK.png

佈局過程簡單來說:

  1. 確定當前組件的佈局邊界
  2. 判斷是否需要重新佈局,如果沒必要會直接返回,反之才需要重新佈局

不需要layout時需要同時滿足當前組件沒有被標記為需要重新佈局父組件傳遞的約束沒有發生變化以及當前組件的佈局邊界也沒有發生變化時
https://ithelp.ithome.com.tw/upload/images/20220926/201089313LoVBpDkbD.png

  1. 調用performLayout() 進行佈局,並且performLayout()又會調用子組件的layout。會進行遞迴來佈局整個widget tree
  2. 請求重繪

以上,是簡單的布局過程,如果有興趣的話,大家能透過trace源碼來了解過程,並且flutter上的註解也是時分得清楚,這裡只簡單的講解,明天開始繼續我們Todo App實做


上一篇
10.flutter的布局(三)
下一篇
12.flutter的布局(五)
系列文
30天學習flutter30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言