美文网首页
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