美文网首页
Flutter中的4颗树 2023-09-05 周二

Flutter中的4颗树 2023-09-05 周二

作者: 勇往直前888 | 来源:发表于2023-09-04 20:32 被阅读0次

    Widget

    • Flutter中几乎所有的对象都是一个widget。比如用于手势检测的GestureDetector 、用于APP主题数据传递的 Theme 等等,都是widget

    • widget的功能是“描述一个UI元素的配置信息”,非常轻量级,随时可以重绘。

    • Widget是不可变的,Widget中定义的属性(即配置信息)必须是不可变的(final)

    • Widget类本身是一个抽象类,我们一般都不用直接继承Widget类来实现一个新组件。

    • 我们通常会通过继承StatelessWidgetStatefulWidget来间接继承widget类。

    4颗树

      1. widget是配置信息,会形成一颗widget树,非常轻量级,不可变,随时会重绘。
      1. 根据 Widget树生成一个Element树,Element 树中的节点都继承自Element类。这是一颗中间树,用于过渡。
      1. 根据Element树生成 Render树(渲染树),渲染树中的节点都继承自RenderObject类。这个负责具体的绘制,比较重量级。使用差量法,尽量减少重绘。
      1. 根据渲染树生成Layer树,然后上屏显示,Layer树中的节点都继承自Layer类。这颗树跟GPU有关,一般由Engine层负责。
    image.png

    三棵树中,WidgetElement 是一一对应的,但并不和 RenderObject一一对应。比如 StatelessWidgetStatefulWidget都没有对应的RenderObject

    StatefulWidget

    • 能保留状态的原因是增加了一个state类。
    abstract class StatefulWidget extends Widget {
      const StatefulWidget({ Key key }) : super(key: key);
        
      @override
      StatefulElement createElement() => StatefulElement(this);
        
      @protected
      State createState();
    }
    
    • widget,它表示与该 State 实例关联的 widget实例,由Flutter 框架动态设置。注意,这种关联并非永久的,因为在应用生命周期中,UI树上的某一个节点的 widget 实例在重新构建时可能会变化,但State实例只会在第一次插入到树中时被创建,当在重新构建时,如果 widget 被修改了,Flutter 框架会动态设置State.widget为新的 widget实例。

    widget经常变,但是State一直是同一个,所以能保持状态。

    • State生命周期
    image.png

    initState只执行一次;build经常执行; 对应的Widget经常变;

    通过Context获取State对象

    • 一般会提供一个of方法对外暴露state,这是一种约定俗成的习惯。

    • 通过state可以实现动态界面。

    Builder(builder: (context) {
      return ElevatedButton(
        onPressed: () {
          // 直接通过of静态方法来获取ScaffoldState
          ScaffoldState _state=Scaffold.of(context);
          // 打开抽屉菜单
          _state.openDrawer();
        },
        child: Text('打开抽屉菜单2'),
      );
    }),
    

    通过GlobalKey获取State对象

    1. 给目标StatefulWidget添加GlobalKey
    //定义一个globalKey, 由于GlobalKey要保持全局唯一性,我们使用静态变量存储
    static GlobalKey<ScaffoldState> _globalKey= GlobalKey();
    ...
    Scaffold(
        key: _globalKey , //设置key
        ...  
    )
    
    1. 通过GlobalKey来获取State对象
    _globalKey.currentState.openDrawer()
    

    通过 RenderObject 自定义 Widget

    • Flutter 最原始的定义组件的方式就是通过定义RenderObject 来实现,而StatelessWidgetStatefulWidget只是提供的两个帮助类。

    类似原生开发的画界面,就要通过RenderObject实现

    • 用来继承的类分为三种:LeafRenderObjectWidget,SingleChildRenderObjectWidget,MultiChildRenderObjectWidget

    • 大概的样子

    class CustomWidget extends LeafRenderObjectWidget{
      @override
      RenderObject createRenderObject(BuildContext context) {
        // 创建 RenderObject
        return RenderCustomObject();
      }
      @override
      void updateRenderObject(BuildContext context, RenderCustomObject  renderObject) {
        // 更新 RenderObject
        super.updateRenderObject(context, renderObject);
      }
    }
    
    class RenderCustomObject extends RenderBox{
    
      @override
      void performLayout() {
        // 实现布局逻辑
      }
    
      @override
      void paint(PaintingContext context, Offset offset) {
        // 实现绘制
      }
    }
    

    相关文章

      网友评论

          本文标题:Flutter中的4颗树 2023-09-05 周二

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