继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

[ -Flutter漫谈篇- ] StatelessWidget Or StatefulWidget

张风捷特烈
关注TA
已关注
手记 72
粉丝 21
获赞 57

http://img.mukewang.com/5d89d94a0001684e06660355.jpg

抉择的条件如果是错误的,那么抉择的本身没有任何意义。----张风捷特烈

人生最难莫过抉择,特别是分不清好坏的时候。To be, or not to be, that is a question
在你Flutter中的第一个抉择也许就是 StatelessWidget Or StatefulWidget
本文就来跟你们说说这两个家伙是干嘛的,有什么不同,该怎么用。


1.描述统一形式化
#define by 张风捷特烈 作用域:本文 [0].用户打开应用到应用进程结束的过程称作一次[会话] [1].具有可视化表现能力的元素,称为[显示元],如一个文字、按钮、图片...   [2].显示元的一切属性集称为[状态],如颜色,大小,样式...   [3].一个显示元在一次会话中的所有状态称为[状态集]   [4].用户看到的一屏显示元组成的集合,称为[界面] [5].一次会话中所有的界面集合,称为[UI] [6].具有改变显示元状态的行为称为[事件] [7].一次会话中所有的事件集合称为[事件集] 设:某显示元的一次会话中[状态集]为 S, 令 |S|表示集合元素个数 定义: StatelessWidget ⇔ |S| = 1 定义: StatefulWidget ⇔ |S| > 1 复制代码

引理1: 状态(s)决定显示元(w)的表现。且s与w一一对应,称为满射 f  记作: w = f(s)  引理2: 事件(e)可以改变显示元状态(s),每个e对应状态,称为映射 g 记作: s = g(e)  推论:w = f(g(e))  f与g的合成映射记作F,则 w = F(e) 复制代码
  • StatelessWidget性质:对于任意e, 有恒定s ⇔ 任意 e,有恒定w


http://img3.mukewang.com/5d89d96e000116d806330252.jpg


  • StatefulWidget性质:存在e, 使 s 变化



http://img4.mukewang.com/5d89da1600015c4406220237.jpg

#define end


1.StatelessWidget : f(x) = 2

如果要显示下面的界面元,在没有任何前提的情况下,选择StatelessWidget
下面是由四个显示元构成的界面,每个显示元一旦诞生就是不可变的

http://img3.mukewang.com/5d89da2800010c3d05620124.jpg

//指定半径,是否选择,颜色,边线色

class ShapeColor extends StatelessWidget {

  ShapeColor(

      {Key key,

      this.radius = 20,

      this.checked = true,

      this.color=Colors.red,

      this.shadowColor=Colors.blue,

      this.elevation=2})

      : super(key: key);

  final double radius; //半径

  final bool checked; //标记是否被选中

  final Color shadowColor; //颜色

  final Color color; //颜色

  final double elevation; //颜色


  @override

  Widget build(BuildContext context) {

    var shape = Container(

      width: radius,

      height: radius,

      decoration: BoxDecoration(//圆形装饰线

        color: color ?? Colors.red,

        shape: BoxShape.circle,

        boxShadow: checked

            ? [

                BoxShadow(//阴影

                  color: shadowColor,

                  offset: Offset(0.0, 0.0),

                  spreadRadius: elevation,

                  blurRadius: elevation

                ),

              ]

            : [],

      ),

    );

    return shape;

  }

}


2.StatefulWidget : g(x) = 2x

由于StatelessWidget本身不可变,但并不意味着它不能借助外界来变
就像 f(x) = 2 是一条不变的横线。 不管x多么努力,都不可能摆脱2的无用命运
如果现在有一个g(x) = 2x , 那 g(f(x)) = 4x 。这时f(x)和 g(x)协作完成了4x
StatefulWidget就像是这个g映射,你没有舞台,我给你,也能发挥你的价值。

http://img.mukewang.com/5d89db2300015e6a04630130.jpg

class ShapeColorRadio extends StatefulWidget {

  ShapeColorRadio({Key key,this.radius = 20,

    this.color=Colors.red,

    this.shadowColor=Colors.blue,

    this.elevation=2}):super(key:key);

  

  final double radius; //半径

  final Color shadowColor; //颜色

  final Color color; //颜色

  final double elevation; //颜色

  @override

  _ShapeColorRadioState createState() => _ShapeColorRadioState();

}


class _ShapeColorRadioState extends State<ShapeColorRadio> {

  var _checked =false;


  @override

  Widget build(BuildContext context) {


    return GestureDetector(

      onTap: (){

        setState(() {//改变状态

          _checked=!_checked;

        });

      },

      child: ShapeColor(

        color: widget.color,

        elevation: widget.elevation,

        shadowColor: widget.shadowColor,

        radius: widget.radius,

        checked: _checked,

      ),

    );

  }

}


3.如何抉择

如果你一开始就意识到需要的是 g(x) = 4x ,你完全可以一步到位。但本质上的逻辑是相同的。
就像你吃草莓蛋糕,可以一口吞,也可以草莓和蛋糕分开吃,最后都在你肚子里。
一口吞简单方便,分开吃你可以单独体会草莓的味道,回味和复用。


class ShapeColorRadio extends StatefulWidget {

  ShapeColorRadio({Key key,this.radius = 20,

    this.color=Colors.red,

    this.shadowColor=Colors.blue,

    this.elevation=2}):super(key:key);


  final double radius; //半径

  final Color shadowColor; //颜色

  final Color color; //颜色

  final double elevation; //颜色

  @override

  _ShapeColorRadioState createState() => _ShapeColorRadioState();

}


class _ShapeColorRadioState extends State<ShapeColorRadio> {

  var _checked =false;


  @override

  Widget build(BuildContext context) {

    var shape = Container(

      width: widget.radius,

      height: widget.radius,

      decoration: BoxDecoration(

        //圆形装饰线

        color: widget.color ?? Colors.red,

        shape: BoxShape.circle,

        boxShadow: _checked

            ? [

          BoxShadow(//阴影

              color: widget.shadowColor,

              offset: Offset(0.0, 0.0),

              spreadRadius: widget.elevation,

              blurRadius: widget.elevation

          ),

        ]

            : [],

      ),

    );

    return GestureDetector(

      onTap: (){

        setState(() {//改变状态

          _checked=!_checked;

        });

      },

      child: shape,

    );

  }

}


4.StatefulWidget得天独厚的优势

StatefulWidget得天独厚的优势在于它有生命周期,initState,didChangeDependencies,didUpdateWidget,reassemble,build,deactivate,dispose。 每个方法都会在组件相应的状态回调,这样看来StatefulWidget更像是一个有生命的东西,而StatelessWidget更像是个死的玩偶。如果你想要去更细粒度地掌控一个组件StatefulWidget是你最佳选择。


http://img.mukewang.com/5d89dba300014f7206600699.jpg



如果你在Widget中写了一个不是final的字段,虽然不会崩,但AS小姐姐会抱怨: "TM,说好的在一起,永远不改变immutable(不可变),你不final是几个意思。"吓得我立马加上final。

http://img2.mukewang.com/5d89dbbb0001dc5106660114.jpg

但有时确实需要有改变的字段怎么办?一个字:用StatefulWidget
如果想在组件移除的时候释放对象怎么办:一个字:用StatefulWidget
什么是用StatelessWidget。f(x) = 2


5.滥用StatefulWidget-机智如你

有人会说,既然StatefulWidget这么好,我都用StatefulWidget不就行了吗?
我反问一句。表达直线 f(x) = 2 。 你会用 f(x) = g(1) 其中g(x) = 2x吗?
如果不会,那就乖乖地垃圾分类。如果觉得无所谓,那随你喽,乱扔垃圾罚得也不是我
食物链能量的传递效率是逐级递减的,只要有传递,就会有损耗。

abstract class StatelessWidget extends Widget {

  const StatelessWidget({ Key key }) : super(key: key);

  @override

  StatelessElement createElement() => StatelessElement(this);

 considerations.

  @protected

  Widget build(BuildContext context);

}


abstract class StatefulWidget extends Widget {

  const StatefulWidget({ Key key }) : super(key: key);

  @override

  StatefulElement createElement() => StatefulElement(this);

  @protected

  State createState();

}

StatelessWidget依靠StatelessElement创建元素,StatefulElement依靠StatefulElement创建元素,他俩有个共同的爹叫ComponentElement,爷爷是Element。所以他俩是兄弟,那么既然同一个爹生的,差别咋就这么大呢?预知后事如何,且听下回分解。

满纸荒唐言,一把辛酸泪。都言作者痴,谁解其中味。



打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP