天天看点

Flutter StatelessWidget,StatefulWidget和它们的生命周期函数StatelessWidget 和 StatefulWidget

这个转自我自己的有道云 想看图片去那里

文档:Day3_2 StatelessWidget 和 StatefulWi…

链接:http://note.youdao.com/noteshare?id=71abe63a08ed806e44911f636b452b44&sub=AC2B27FCC2AA41FE86AB93B15475B063

StatelessWidget 和 StatefulWidget

  • StatelessWidget 的案例
  • StatefulWidget 的案例
  • StatefulWidget的生命周期

1. StatelessWidget

我们经过之前的练习知道了, 这个东西是无状态的Widget, 他的数据是不能变的

StatelessWidget练习

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rzraKNvW-1583548791492)(4DAC89A36141444591BDE15A137B9CC5)]

我们从头写起

import 'package:flutter/material.dart';

main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

           

然后把框架搭好

  • 我们发现直接写extends StatelessWidget速度太慢, 所以这里可以使用一个快速的写法
  • 我们写出stl 然后回车就可以快速打出 对应的继承代码
  • 但是我们要使用material的样式而且要展示home界面所以需要这样嵌套

Scaffold 这个东西就像Android中的Activity 是一样的

import 'package:flutter/material.dart';

main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: HYHomePage()
    );
  }
}

class HYHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("StatelessWidget练习")
      ),
      body: HYHomeList(),
    );
//    注意这里和java 那些东西不一样需要加分号
  }
}

class HYHomeList extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ;
  }
}

           

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IQuy2NTk-1583548791494)(D1785F6E751A4EA58D078E59808124EE)]

然后我们观察这个项目的结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hHjZXyaw-1583548791496)(93E9474DD60046048B3C898ACE94CA6F)]

我们先写出框架

  • 因为我们这里是从上往下放多个所以这里是Column
  • 如果是放多个就是children, 放一个就是child
import 'package:flutter/material.dart';

main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: HYHomePage()
    );
  }
}

class HYHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("StatelessWidget练习")
      ),
      body: HYHomeList(),
    );
//    注意这里和java 那些东西不一样需要加分号
  }
}

class HYHomeList extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        Text("hahah"),
        Text("hahha"),
        Text("hahaha")
      ],
    );
  }
}

           

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TTcdlZnL-1583548791496)(4187A953B1F14A46AFDD2E12ECFEA8C6)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HIOeRhl7-1583548791497)(93E9474DD60046048B3C898ACE94CA6F)]

这个里面也是一个Column

HYHomeListItem 的设计

  • 因为这个很明显, 他需要显示不同的内容
  • 我们flutter是一个面向对象的语言

所以我们的Widget可以设置成要传参数的那种

import 'package:flutter/material.dart';

main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: HYHomePage()
    );
  }
}

class HYHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("StatelessWidget练习")
      ),
      body: HYHomeList(),
    );
//    注意这里和java 那些东西不一样需要加分号
  }
}

class HYHomeList extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        HYHomeListItem("title", "desc", "https://www.lianaiyx.com/d/file/GalGame/2019-04-22/b0201606065bcdad3159cd02c9199a01.jpg"),
        HYHomeListItem("title", "desc", "https://www.lianaiyx.com/d/file/GalGame/2019-07-27/c4d6ea4d8c51e0aa3c750aed13913a1b.jpg"),
        HYHomeListItem("title", "desc", "https://www.lianaiyx.com/d/file/celve/2019-03-04/55ce1f75dac4b12a4aae1ec691b83400.jpg")
      ],
    );
  }
}


class HYHomeListItem extends StatelessWidget {
  final String title;
  final String desc;
  final String imageURL;

  HYHomeListItem(this.title, this.desc, this.imageURL);

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        Text(title),
        Text(desc),
        Image.network(imageURL)
      ],
    );
  }
}

           

所以这个里面也是item Widget

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vG7qnv4P-1583548791497)(70C3F731820246E7ADC926AA5AE6A1C2)]

但是下面报错了

A RenderFlex overflowed by 285 pixels on the bottom.

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8uKNOSol-1583548791498)(2C12B763EB14423AA00843860FD9CEC9)]

意思是说超出了, 我们的Widget超出了屏幕的范围

我们换用ListView代替最外面的Column, 让最外面可以滚动这个问题就可以解决了

import 'package:flutter/material.dart';

main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: HYHomePage()
    );
  }
}

class HYHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("StatelessWidget练习")
      ),
      body: HYHomeList(),
    );
//    注意这里和java 那些东西不一样需要加分号
  }
}

class HYHomeList extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ListView(
      children: <Widget>[
        HYHomeListItem("title", "desc", "https://www.lianaiyx.com/d/file/GalGame/2019-04-22/b0201606065bcdad3159cd02c9199a01.jpg"),
        HYHomeListItem("title", "desc", "https://www.lianaiyx.com/d/file/GalGame/2019-07-27/c4d6ea4d8c51e0aa3c750aed13913a1b.jpg"),
        HYHomeListItem("title", "desc", "https://www.lianaiyx.com/d/file/celve/2019-03-04/55ce1f75dac4b12a4aae1ec691b83400.jpg")
      ],
    );
  }
}


class HYHomeListItem extends StatelessWidget {
  final String title;
  final String desc;
  final String imageURL;

  HYHomeListItem(this.title, this.desc, this.imageURL);

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        Text(title),
        Text(desc),
        Image.network(imageURL)
      ],
    );
  }
}

           

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K1Vlbhnt-1583548791499)(0D7949F3C6174E9CA7E2DAFCA985B5A3)]

但是如果我们不希望你居中

  • 这个时候我们可以设置itemWidget中的Column交叉轴属性

但是这个不是一般的做法

class HYHomeListItem extends StatelessWidget {
  final String title;
  final String desc;
  final String imageURL;

  HYHomeListItem(this.title, this.desc, this.imageURL);

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.end,
      children: <Widget>[
        Text(title),
        Text(desc),
        Image.network(imageURL)
      ],
    );
  }
}

           

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6Kp0vHDe-1583548791499)(CEB3740EDFFA40BFBC904B41995AF078)]

这样我们就可以居左居右了

  • 但是如果你想title居左 desc居右 那我们就需要在里面再嵌入Row让里面的东西可以自行设置他的居左居右
  • 注意这个Row是占据一整行的

这个就是一般做法

class HYHomeListItem extends StatelessWidget {
  final String title;
  final String desc;
  final String imageURL;

  HYHomeListItem(this.title, this.desc, this.imageURL);

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.end,
      children: <Widget>[
        Row(
          mainAxisAlignment: MainAxisAlignment.start,
          children: <Widget>[
            Text(title),
          ],
        ),
        Row(
          mainAxisAlignment: MainAxisAlignment.end,
          children: <Widget>[
            Text(desc),
          ],
        ),
        Image.network(imageURL)
      ],
    );
  }
}

           

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5E7i9OH3-1583548791500)(42F45FFB5A8F4AAF97CBB0D7B7292AFC)]

调整样式

class HYHomeListItem extends StatelessWidget {
  final String title;
  final String desc;
  final String imageURL;

  HYHomeListItem(this.title, this.desc, this.imageURL);

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.end,
      children: <Widget>[
        Row(
          mainAxisAlignment: MainAxisAlignment.start,
          children: <Widget>[
            Text(title, style: TextStyle(fontSize: 30, color: Colors.red),),
          ],
        ),
        Row(
          mainAxisAlignment: MainAxisAlignment.end,
          children: <Widget>[
            Text(desc, style: TextStyle(fontSize: 20, color: Colors.blue)),
          ],
        ),
        Image.network(imageURL)
      ],
    );
  }
}

           

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OSjgRgGM-1583548791500)(53C41C5F1A61452CA6364E5469558B1E)]

设置外边距

然后我如果希望这些Widget间有些间距的话我们可以使用SizedBox

  • 一般来说如果我们使用的是html那种东西的话, 我们因该是设置类似于margin-top 之类的东西
  • 但是在flutterz中我们没有这种东西
  • 所以我们为了撑高度使用的是SizedBox(height: number)
  • 如果想要左右边距的话我们使用Alignment就可以了

因为flutter中万物皆Widget所以margin 这种也是属于Widget的(当然有些是属于widget的属性的)

class HYHomeList extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ListView(
      children: <Widget>[
        HYHomeListItem("title", "desc", "https://www.lianaiyx.com/d/file/GalGame/2019-04-22/b0201606065bcdad3159cd02c9199a01.jpg"),
        SizedBox(height: 10),
        HYHomeListItem("title", "desc", "https://www.lianaiyx.com/d/file/GalGame/2019-07-27/c4d6ea4d8c51e0aa3c750aed13913a1b.jpg"),
        SizedBox(height: 10),
        HYHomeListItem("title", "desc", "https://www.lianaiyx.com/d/file/celve/2019-03-04/55ce1f75dac4b12a4aae1ec691b83400.jpg")
      ],
    );
  }
}


class HYHomeListItem extends StatelessWidget {
  final String title;
  final String desc;
  final String imageURL;

  HYHomeListItem(this.title, this.desc, this.imageURL);

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.end,
      children: <Widget>[
        Row(
          mainAxisAlignment: MainAxisAlignment.start,
          children: <Widget>[
            Text(title, style: TextStyle(fontSize: 30, color: Colors.red),),
          ],
        ),
        SizedBox(height: 8),
        Row(
          mainAxisAlignment: MainAxisAlignment.end,
          children: <Widget>[
            Text(desc, style: TextStyle(fontSize: 20, color: Colors.blue)),
          ],
        ),
        SizedBox(height: 8),
        Image.network(imageURL)
      ],
    );
  }
}

           

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NhdSW4xF-1583548791501)(F5D7CDE5D2364A4DB592BAC917707F2F)]

设置内边距

如果我们觉得这个东西挨着边框不好看

那么我们可以设置他的padding

这个东西padding: EdgeInsets.all(8) 直接在ListView上面加

class HYHomeList extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ListView(
      padding: EdgeInsets.all(8),
      children: <Widget>[
        HYHomeListItem("title", "desc", "https://www.lianaiyx.com/d/file/GalGame/2019-04-22/b0201606065bcdad3159cd02c9199a01.jpg"),
        SizedBox(height: 10),
        HYHomeListItem("title", "desc", "https://www.lianaiyx.com/d/file/GalGame/2019-07-27/c4d6ea4d8c51e0aa3c750aed13913a1b.jpg"),
        SizedBox(height: 10),
        HYHomeListItem("title", "desc", "https://www.lianaiyx.com/d/file/celve/2019-03-04/55ce1f75dac4b12a4aae1ec691b83400.jpg")
      ],
    );
  }
}
           

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-d1KU53zu-1583548791502)(435875AA074941298D05F5D119E78BE3)]

设置边框

然后我们觉得这个还是有一个边框比较好

这个东西因该加在item上面但是item没有这个属性

  • 边框这个东西需要Container来设置, 其实就是一个普通的Widget
  • 因为Column是装多个widget给他设置border肯定不合适
  • 这里我们使用alt + enter 加上container包裹的快捷键
  • 然后设置Container的border
class HYHomeListItem extends StatelessWidget {
  final String title;
  final String desc;
  final String imageURL;

  HYHomeListItem(this.title, this.desc, this.imageURL);

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.all(8),
      decoration: BoxDecoration(
        border: Border.all(
          width: 5,
          color: Colors.red
        ),
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.end,
        children: <Widget>[
          Row(
            mainAxisAlignment: MainAxisAlignment.start,
            children: <Widget>[
              Text(title, style: TextStyle(fontSize: 30, color: Colors.red),),
            ],
          ),
          SizedBox(height: 8),
          Row(
            mainAxisAlignment: MainAxisAlignment.end,
            children: <Widget>[
              Text(desc, style: TextStyle(fontSize: 20, color: Colors.blue)),
            ],
          ),
          SizedBox(height: 8),
          Image.network(imageURL)
        ],
      ),
    );
  }
}
           

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ifyRVLwW-1583548791502)(7C13287C51C046158B01D00FF54A0653)]

StatalessWidget完整代码

import 'package:flutter/material.dart';

main() => runApp(MyApp());

//直接写效率太低了
//我们直接敲stl就会生成对应的代码
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return MaterialApp(
      home: HYHomePage(),
//      这个就是一启动显示的页面
    );
  }
}

class HYHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
          title: Text("商品列表")
      ),
      body: HYHomeContent(),
    );
  }
}

class HYHomeContent extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
//    现在只是想回顾一下这个StatelessWidget
    return ListView(
//      要放多个 所以是children 不是 child
      children: <Widget>[
//        我们因该在里面放商品数据
//      The specific RenderFlex in question is: RenderFlex#af73a relayoutBoundary=up1 OVERFLOWING
//      这个是操作布局边界 希望让它变成可滚动的区域
        HYHomeProductItem("title", "desc", "https://www.lianaiyx.com/d/file/GalGame/2019-04-22/b0201606065bcdad3159cd02c9199a01.jpg"),
        SizedBox(height: 6),
        HYHomeProductItem("title", "desc", "https://www.lianaiyx.com/d/file/GalGame/2019-07-27/c4d6ea4d8c51e0aa3c750aed13913a1b.jpg"),
        SizedBox(height: 6),
        HYHomeProductItem("title", "desc", "https://www.lianaiyx.com/d/file/GalGame/2019-03-05/6c815fb726391c117d1d6b0a126fa643.jpg"),
      ],
    );
  }
}

//我们使用同一个Widget但是我们希望展示的东西是不一样的
//
class HYHomeProductItem extends StatelessWidget {
  final String title;
  final String desc;
  final String imageURL;

  final style1 = TextStyle(fontSize: 25, color: Colors.orange);
  final style2 = TextStyle(fontSize: 20, color: Colors.green);
  HYHomeProductItem(this.title, this.desc, this.imageURL);

  @override
  Widget build(BuildContext context) {

//    我们现在想要设计一个边框
//    如果想要包裹一个widget我们可以使用alt + enter
    return Container(
//      如果我们希望和里面的东西有一个内边距
      padding: EdgeInsets.all(12),
//      decoration这个东西是一个抽象类
      decoration: BoxDecoration(
//        ctrl + alt + B 就可以看到它的实现类
          border: Border.all(
//          这个东西就是设置边框的宽度
              width: 5,
//          设置边框颜色
              color: Colors.black12
//            这个12是一个透明度的意思
          )
      ),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.end,
//        但是实际上我们因该通过 交叉轴而是在里面嵌套 Row然后在里面
        children: <Widget>[
//          我们想要居右
//          , textAlign: TextAlign.right 这个没有用 文本是包裹内容的所以居左居右
//        这个东西是Column所以我们设置的是它的交叉轴
          Row(
            mainAxisAlignment: MainAxisAlignment.end,
            children: <Widget>[
              Text(title, style: style1, textAlign: TextAlign.right),
            ],
          ),
//        flutter没有margin-top之类的东西所以
          SizedBox(height: 8),
          Row(
            children: <Widget>[
              Text(desc, style: style2),
            ],
          ),
//        这个八个像素 但是是和设备有关系
//      后面
//        如果是想要左右边距离的话Alignmen就可以了
          SizedBox(height: 8),
          Row(
            children: <Widget>[
              Image.network(imageURL)
            ],
          )
        ],
      ),
    );
  }
}

           

2. StatefulWidget的使用示例

  • 为什么flutter在设计的时候StatefulWidget的build方法放在State中
    1. build出来的Widget是需要以来State中的变量(状态)
    2. flutter运行过程中Widget是不断销毁创建的 Element-Render-Object
  • 当时我们状态发生改变的时候, 并不希望创建一个新的State

所以我们呢才会将StatefulWidget和State实现类分离

实例

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZVuEUKM7-1583548791502)(1FF62F62A746427D8D1194B6D6714C51)]

  • 首先我们搭建出平台
import "package:flutter/material.dart";

main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return HYHomePage();
  }
}

class HYHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HYHomeContent(),
    );
  }
}

class HYHomeContent extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("statefulWidget示例"),
      ),
      body: Text("test")
    );
  }
}

           

如果我们要做计数器很明显我们需要具有状态的Widget

所以就需要用StatefulWidget

import "package:flutter/material.dart";

main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HYHomePage(),
    );
  }
}

class HYHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("statefulWidget示例"),
      ),
      body: Text("test")
    );
  }
}

class HYHomeContent extends StatefulWidget {
  @override
  _HYHomeContentState createState() => _HYHomeContentState();
}

class _HYHomeContentState extends State<HYHomeContent> {
  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

           

然后就是结构和StatelessWidget不同是的我们的渲染的框架是在继承StatefulWidget, 因该是写在State里面

import "package:flutter/material.dart";

main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HYHomePage(),
    );
  }
}

class HYHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("statefulWidget示例"),
      ),
      body: Center(child:HYHomeContent())
    );
  }
}

class HYHomeContent extends StatefulWidget {
  @override
  _HYHomeContentState createState() => _HYHomeContentState();
}

class _HYHomeContentState extends State<HYHomeContent> {
  int _counter = 0;

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            RaisedButton(
              color: Colors.red,
              child: Text("+", style: TextStyle(color: Colors.white)),
              onPressed: () {

              },
            ),
            RaisedButton(
              color: Colors.green,
              child: Text("-", style: TextStyle(color: Colors.white)),
              onPressed: () {

              },
            )
          ],
        ),
        Text("counter: $_counter")
      ],
    );
  }
}

           

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TshD7TJE-1583548791503)(236D8204F87B4A6283A0CD5579F74810)]

但是我们直接改变变量的值还是不行的

  • 我们必须要调用setState刷新
  • 这个东西就是调用刷新页面的意思, 所以你如果把变量的改变写在前面写在后面都是一样的
  • 再强调一遍私有属性是会加_ 加了只有这个变量就会只属于这个 库
  • 这个注意 这里如果要分离State的作为一个新的widget则是是需要将我们的函数作为闭包传过去 然后在那边调用
import "package:flutter/material.dart";

main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HYHomePage(),
    );
  }
}

class HYHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("statefulWidget示例"),
      ),
      body: Center(child:HYHomeContent())
    );
  }
}

class HYHomeContent extends StatefulWidget {
  @override
  _HYHomeContentState createState() => _HYHomeContentState();
}

class _HYHomeContentState extends State<HYHomeContent> {
  int _counter = 0;

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            RaisedButton(
              color: Colors.red,
              child: Text("+", style: TextStyle(color: Colors.white)),
              onPressed: () {
                ++_counter;
                setState(() {

                });
              },
            ),
            RaisedButton(
              color: Colors.green,
              child: Text("-", style: TextStyle(color: Colors.white)),
              onPressed: () {
                setState(() {
                  --_counter;
                });
              },
            )
          ],
        ),
        Text("counter: $_counter")
      ],
    );
  }
}
           

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fvcLFTYQ-1583548791503)(6C3739A610094A2F8631AC662BDBC587)]

我们看到源码里面其实它也是在setState里面调了传进去的参数的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aTQ4ALCN-1583548791504)(04E6A1BEBEDD4139A8BCC168D705E8AD)]

指向StatefulWidget的指针

还有如果你想要再StatefulWidget中传参数 然后再后面展示

可以再传的方式 也可以用state指向StatefulWidget对象的指针来实现这个功能

class HYHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("statefulWidget示例"),
      ),
      body: Center(child:HYHomeContent("传递的参数"))
    );
  }
}

class HYHomeContent extends StatefulWidget {
  final String message;

  HYHomeContent(this.message);

  @override
  _HYHomeContentState createState() => _HYHomeContentState();
}

class _HYHomeContentState extends State<HYHomeContent> {
  int _counter = 0;

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            RaisedButton(
              color: Colors.red,
              child: Text("+", style: TextStyle(color: Colors.white)),
              onPressed: () {
                ++_counter;
                setState(() {

                });
              },
            ),
            RaisedButton(
              color: Colors.green,
              child: Text("-", style: TextStyle(color: Colors.white)),
              onPressed: () {
                setState(() {
                  --_counter;
                });
              },
            )
          ],
        ),
        Text("counter: $_counter ${widget.message}")
      ],
    );
  }
}
           

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tKOKjZkB-1583548791505)(79250287C7004999B1970578F4AACF0D)]

3. StatfulWidget和StatelessWidget的生命周期函数

  • 生命周期函数也被称为“hook” “钩子函数”
  • 其主要功能就是在程序运行到指定位置时进行回调
  • 生命周期函数的功能
    1. 初始化一些数据, 变量, 状态
    2. 发送网络请求
    3. 监听组件中的事件 controller 添加监听事件(滚动事件)
    4. 管理内存: 一些定时器-controller手动进行销毁

StatelessWidget的生命周期函数很简单

主要就是StatelessWidget构造函数和build函数

其实就是没有专门的生命周期函数, 因为它没有状态, 所以它也简单的多

import "package:flutter/material.dart";

main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HYHomePage()
    );
  }
}

class HYHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("title")
      ),
      body: HYHomeContent()
    );
  }
}

class HYHomeContent extends StatelessWidget {

  HYHomeContent() {
    print("HYHomeContent 构造函数执行");
  }

  @override
  Widget build(BuildContext context) {
    print("HYHomeConten build函数执行");
    return Text("content");
  }
}


           

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XxPaQwMg-1583548791505)(530E35C0AA264130B6EC3915933ECDE0)]

StatefulWidget的生命周期函数

重要

先建立一个简单的StatefulWidget

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ip2UwgJp-1583548791505)(5CF4FCB23BB740C7A6855B909120D2CB)]

import "package:flutter/material.dart";

main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HYHomePage()
    );
  }
}

class HYHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("StatefulWidget的生命周期函数")
      ),
      body: HYHomeContent()
    );
  }
}

class HYHomeContent extends StatefulWidget {
  @override
  _HYHomeContentState createState() => _HYHomeContentState();
}

class _HYHomeContentState extends State<HYHomeContent> {
  int _counter = 0;

//  如果我们想要拆分这个东西因该怎么办
  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        RaisedButton(
          child: Text("+"),
          onPressed: () {
            setState(() {
              _counter++;
            });
          },
        ),
        Text("counter: $_counter")
      ],
    );
  }
}

           

然后将生命周期函数写上去

  1. StatefulWidget子类的构造方法
  2. StatefulWidget子类的createState方法
  3. State子类的构造方法
  4. State子类的initState方法
  5. State子类的build方法
  6. State子类的dispose方法
import "package:flutter/material.dart";

main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HYHomePage()
    );
  }
}

class HYHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("StatefulWidget的生命周期函数")
      ),
      body: HYHomeContent()
    );
  }
}

class HYHomeContent extends StatefulWidget {
  HYHomeContent() {
    print("1. 调用HYHomeContent的构造函数");
  }

  @override
  _HYHomeContentState createState() {
    print("2. 调用HYhomeContent的createState方法");
    return _HYHomeContentState();
  }
}

class _HYHomeContentState extends State<HYHomeContent> {
  int _counter = 0;

  _HYHomeContentState() {
    print("3. 调用_HYHomeContentState的构造函数");
  }

  @override
  void initState() {
    // TODO: implement initState
    print("4. 调用_HYHomeContentState的initState方法");
//    下面这个必须写
    super.initState();
  }

//  如果我们想要拆分这个东西因该怎么办
  @override
  Widget build(BuildContext context) {
    print("5.  调用_HYHomeContentState的build方法");
    return Column(
      children: <Widget>[
        RaisedButton(
          child: Text("+"),
          onPressed: () {
            setState(() {
              _counter++;
            });
          },
        ),
        Text("counter: $_counter")
      ],
    );
  }

  @override
  void dispose() {
    // TODO: implement dispose
    print("6. 调用_HYHomeContentState的dispose方法");
    super.dispose();
  }
}

           

后面这个反复调用是Android Studio 的bug, vscode就没有

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mqD1bPq3-1583548791506)(B0C29EE84CBF40A4B8090FBCF3943420)]

  • 在我们点击+以后 会不停的调用build
  • 这个过程其实也就是不停重建Widget过程
  • 这个也是验证了Widget是不停的销毁和创建的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1dshXOXz-1583548791506)(F25C1882E1ED4A8DB29BD6B0A6EFAEA8)]

还有一些其他的生命周期函数那些不是很常用但是还是需要知道

import "package:flutter/material.dart";

main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HYHomePage()
    );
  }
}

class HYHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("StatefulWidget的生命周期函数")
      ),
      body: HYHomeContent()
    );
  }
}

class HYHomeContent extends StatefulWidget {
  HYHomeContent() {
    print("1. 调用HYHomeContent的构造函数");
  }

  @override
  _HYHomeContentState createState() {
    print("2. 调用HYhomeContent的createState方法");
    return _HYHomeContentState();
  }
}

class _HYHomeContentState extends State<HYHomeContent> {
  int _counter = 0;

  _HYHomeContentState() {
    print("3. 调用_HYHomeContentState的构造函数");
  }

  @override
  void initState() {
    // TODO: implement initState
    print("4. 调用_HYHomeContentState的initState方法");
//    下面这个必须写
    super.initState();
  }

  @override
  void didUpdateWidget(HYHomeContent oldWidget) {
    // TODO: implement didUpdateWidget
    print("调用——HYHomeContentState的didUpdateWidget方法");
    super.didUpdateWidget(oldWidget);
  }

  @override
  void didChangeDependencies() {
    // TODO: implement didChangeDependencies
    //    這個數據依賴一些東西的時候 依賴的東西改變了就會調用
//    就是裏面的東西 假如依賴了 InheritedWidget的message 假如這個改變了
//  就會調用didChangeDependecies
    print("调用_HYHomeContenState的didChangeDepancies");
    super.didChangeDependencies();
  }

//  如果我们想要拆分这个东西因该怎么办
  @override
  Widget build(BuildContext context) {
    print("5.  调用_HYHomeContentState的build方法");
    return Column(
      children: <Widget>[
        RaisedButton(
          child: Text("+"),
          onPressed: () {
            setState(() {
              _counter++;
            });
          },
        ),
        Text("counter: $_counter")
      ],
    );
  }

  @override
  void dispose() {
    // TODO: implement dispose
    print("6. 调用_HYHomeContentState的dispose方法");
    super.dispose();
  }
}

           

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WtZcALT6-1583548791507)(B51E30A28D63489492042D24E7DF0BA4)]