Flutter基础(1)

Flutter介绍和dart基础语法(1) Flutter是谷歌的移动UI框架,可以快速在iOS和Android上构建高质量的原生用户界面。 Flutter可以与现有的代码一起工作。在全世界,Flutter正在被越来越多的开发者和组织使用,并且Flutter是完全免费、开源的。 Flutter特性: 1.快速开发 Flutter的热重载可帮助您快速地进行测试、构建UI、添加功能并更快地修复错误。通过将更新的源代码文件注入正在运行的Dart VM(虚拟机)中工作。这不仅包括添加新类,还包括向现有类添加方法和字段,以及更改现有函数。在iOS和And 阅读详情

一.创建新的Flutter工程

  1. 使用终端进行创建 不支持大写字母,可以加下划线
    创建成功后,可以使用VSCode或者Android studio打开
flutter create 项目名

  1. 工程内容
    lib文件夹:存放编写的代码,main.dart即为启动入口

  1. 项目启动
    打开iOS或者安卓模拟器, 在工具栏找到启动调试,点击进行启动

二、flutter项目编写

  1. flutter项目的几个特性
    热重载 hot reload 、   热重启 restart
    运行一个flutter项目有三种方式:  冷启动:(从0启动)、 热重载 (最主要是执行build方法,其他方法不受影响)、 热重启(重新运行整个项目)
    使用热重载可以快速预览布局变化,但是只有build方法会重置

  1. 简单编写启动内容
    导入头文件(package:flutter/material.dart), 然后调用runApp函数
import 'package:flutter/material.dart';

main(List<String> args) {
  runApp(Text("Hello world", textDirection: TextDirection.ltr));
}

  1. 具体内容设置
    textDirection  传入文字方向
    style  设置样式,字体颜色等
    Center 也是一个Widget,实现居中操作
runApp(Center(
  child: Text("Hello world",
      textDirection: TextDirection.ltr,
      style: TextStyle(fontSize: 30, color: Colors.red))));

三、Widget介绍

  1. Widget  即组件
    万物皆是Widget, 通过嵌套Widget来实现布局功能
    • 有状态的Widget:
      StatefulWedget 在运行过程中有一些状态(data数据)需要改变
    • 无状态的Widget:
      StatelessWidget 内容是确定的,没有状态(data数据)的改变

  2. 几种常用Widget

  • MaterialApp  会自动添加某些默认配置,不需要手动进行设置,比如文字方向等
 runApp(MaterialApp(
  home: Center(
      child: Text("Hello World",
          style: TextStyle(fontSize: 30, color: Colors.orange)))));
  • Scaffold  脚手架   用于快速搭建页面  创建导航栏、Tabbar等
    主要参数有 appBar(导航栏或者Tabbar),body(界面内容)
runApp(MaterialApp(
  debugShowCheckedModeBanner: false,
  home: Scaffold(
      appBar: AppBar(
          title: Text(
        "第一个项目",
        style: TextStyle(fontSize: 20, color: Colors.white),
      )),
      body: Center(
          child: Text("Hello world",
              textDirection: TextDirection.ltr,
              style: TextStyle(fontSize: 30, color: Colors.red))))));

3.自定义Widget子类

class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      // TODO: implement build
      return Text("hello World");
    }
  }

build方法: 在创建自定义Widget子类时,会执行它的build方法,返回一个希望渲染的Widget元素,例如上例所示的Text Widget

StatelessWidget没办法去主动执行build方法,当我们的数据发生改变的时候,build方法会被重新执行(setState)

  • build方法在什么情况下会执行?
    1)当对应的StatelessWidget第一次被插入到Widget树中时,即第一次创建时
    2) 当对应的父Widget发生改变时,子Widget会被重新构建
    3) 如果对应的Widget依赖inheritedWidget的一些数据,inheritedWidget数据发生改变时

将需要构造的Widget放到build方法中返回,然后直接调用编写的Widget子类,即可得到想要的界面```

main(List<String> args) {
        runApp(MyApp());
      }

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        debugShowCheckedModeBanner: false,
        home: Scaffold(
            appBar: AppBar(
                title: Text(
              "第一个项目",
              style: TextStyle(fontSize: 20, color: Colors.white),
            )),
            body: Center(
                child: Text("Hello world",
                    textDirection: TextDirection.ltr,
                    style: TextStyle(fontSize: 30, color: Colors.red)))));
  }
}

4.代码拆分抽取
将各个Widget包装成一个个自定义Widget子类,再进行组合,完成代码的拆分重组

main(List<String> args) {
  runApp(MyApp());
}

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

class HomePageView extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
            title: Text(
          "第一个项目",
          style: TextStyle(fontSize: 20, color: Colors.white),
        )),
        body: ContentBody());
  }
}

class ContentBody extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
        child: Text("Hello world",
            textDirection: TextDirection.ltr,
            style: TextStyle(fontSize: 30, color: Colors.orange)));
  }
}

5.一行写入多个控件
横向写入多个控件  Row
竖向写入多个控件  Column

class ContentBody extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
        child: Row(mainAxisAlignment: MainAxisAlignment.center, children: [
      Text("111"),
      Text("Hello world",
          textDirection: TextDirection.ltr,
          style: TextStyle(fontSize: 30, color: Colors.orange))
    ]));
  }
}

默认从每行的最左端开始布局,使用mainAxisAlignment参数可以改变行内的布局位置


6. @immutable修饰符

  • 使用@immutable 注解标明的类及其子类均为不可变类,其中的属性均不可变,使用final修饰,不可定义状态
    Widget类使用@immutable标记,所有的Widget都不可以直接定义状态
  • StatelessWidget即是不可更改的类,不可定义状态
  • StatefulWidget内部有一个抽象方法createState,此方法返回一个State类
  • 在自定义的State子类中通过重写build方法实现控件
  • StatefulWidget内部不可直接定义状态,但是可以在自定义的State子类中可以定义状态

class ContentBody extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return ContentBodyState();
  }
}

class _ContentBodyState extends State<ContentBody> {
  var flag = true;

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Center(
        child: Row(mainAxisAlignment: MainAxisAlignment.center, children: [
      Checkbox(
          value: flag,
          onChanged: (value) {
            setState(() {
              flag = value ?? false;
            });
          }),
      Text("Hello world",
          textDirection: TextDirection.ltr,
          style: TextStyle(fontSize: 30, color: Colors.orange))
    ]));
  }
}

总结:
继承自StatefulWidget的类负责实现createState方法,返回一个State类
State类负责实现Build方法,以及状态的创建,来实现功能

另外需要注意的几点:

  • 状态的改变需要在setState回调执行完毕之前进行,否则不生效
  • State类一般使用下划线开头,如_ContentBodyState,下划线开头的类在别的文件无法访问,保证安全,而继承自StatefulWidget的类不加下划线

问题1:上述示例中,ContentBody返回的State类一定要定义为ContentBody泛型吗?可以改成别的StatefulWidget类吗?

可以,但没必要。
语法上无问题,但是,定义成此泛型,才可以使用系统提供的一个widget属性来构建出桥梁,连通对应的StatefulWidget子类,所以一般会这么写

问题2:继承自StatefulWidget的类,具体的作用?

1). 生成返回State类
2). 可以接收父Widget传过来的数据

四、使用StatelessWidget完成竖向列表布局

StatelessWidget子类代码块生成快捷键:  stle
上篇已经简单介绍了StatelessWidget的基本使用,接下来简单介绍如何使用StatelessWidget创建一个商品列表,效果如下:

  1. StatelessWidget参数传递
    与Dart语法一致,创建属性(final修饰),实现初始化方法,进行赋值 调用:
 
class YWHomeProduct extends StatelessWidget {
  final String title;
  final String desc;
  final String imageUrl;

  YWHomeProduct(this.title, this.desc, this.imageUrl);

  @override
  Widget build(BuildContext context) {
    return Column(children: [Text(title), Text(desc), Image.network(imageUrl)]);
  }
}
YWHomeProduct("瓜子", "焦糖瓜子,香甜可口",
      "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.yzcdn.cn%2Fupload_files%2F2018%2F08%2F21%2FFiLdNHrxKMohbPJ2QbtOTo9MhIMm.jpg%3FimageView2%2F2%2Fw%2F580%2Fh%2F580%2Fq%2F75%2Fformat%2Fjpg&refer=http%3A%2F%2Fimg.yzcdn.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1632121924&t=b37df3a44a89fc3b768c0f3f69f94f2a")
 

2.竖向列表

  • column: 竖向布局多个控件,使用column布局,当竖向控件高度超出屏幕高度后,会显示条纹遮挡
  • ListView: 竖向可滚动控件

3.对象创建:
函数内部可以创建局部变量,减小语句内部代码量,但是每次调用函数都会创建
在类的内部创建变量,则只会在对象实例化时创建一次
在类的外部创建变量,则在整个项目生命周期中都会存在

4.创建控件之间的边距
可以通过SizedBox控件来实现,横向距离width,竖向距离height

SizedBox(height: 8)

5.边框创建
将某个控件放置到Container中,可以用Container来设置边框(decoration)以及内边距(padding)等
问题:BoxDecoration的主要用处?

return Container(
    padding: EdgeInsets.all(8),
    decoration:
        BoxDecoration(border: Border.all(color: Colors.purple, width: 8)),
    child: Column(children: [
      Text(title, style: titleStyle),
      SizedBox(height: 8),
      Text(desc, style: descStyle),
      SizedBox(height: 8),
      Image.network(imageUrl)
    ]));

用于Widget的装饰

color	      颜色背景	       Color类型
image	      图片背景	       DecorationImage类型
border	      边界	        BoxBorder类型
borderRadius  圆角边界半径	 BorderRadiusGeometry类型
boxShadow	  阴影  	        List<BoxShadow>类型
gradient	  渐变色	       Gradient类型
backgroundBlendMode	背景混合模式	  BlendMode类型
shape	      形状	        BoxShape类型

6.控制column竖向布局控件位置
控件分为主轴(竖向)和交叉轴(横向)
主轴使用MainAxisAlignment控制子控件位置
交叉轴使用CrossAxisAlignment控制子控件位置
通过Flex可以决定主轴和交叉轴

Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
      Text(title, style: titleStyle),
      SizedBox(height: 8),
      Text(desc, style: descStyle),
      SizedBox(height: 8),
      Image.network(imageUrl)
    ])

下面是完整的代码:

import 'package:flutter/material.dart';

main(List<String> args) {
  runApp(MyApp());
}

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

class YWHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(appBar: AppBar(title: Text("购物车")), body: YWBodyContent());
  }
}

class YWBodyContent extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ListView(children: [
      YWHomeProduct("瓜子", "焦糖瓜子,香甜可口",
          "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.yzcdn.cn%2Fupload_files%2F2018%2F08%2F21%2FFiLdNHrxKMohbPJ2QbtOTo9MhIMm.jpg%3FimageView2%2F2%2Fw%2F580%2Fh%2F580%2Fq%2F75%2Fformat%2Fjpg&refer=http%3A%2F%2Fimg.yzcdn.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1632121924&t=b37df3a44a89fc3b768c0f3f69f94f2a"),
      YWHomeProduct("花生", "盐水花生,补气养血",
          "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fi2.chuimg.com%2F25d9caf08b6811e6a9a10242ac110002_1171w_801h.jpg%3FimageView2%2F2%2Fw%2F660%2Finterlace%2F1%2Fq%2F90&refer=http%3A%2F%2Fi2.chuimg.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1632122384&t=f3859622328496babe08d62ffca276ba"),
      YWHomeProduct("八宝粥", "居家旅行,出门良品",
          "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fcp2.douguo.net%2Fupload%2Fdish%2F7%2F3%2F3%2F600_7355c671e3bf52100c61e043c6110ae3.jpg&refer=http%3A%2F%2Fcp2.douguo.net&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1632122038&t=cedcc17ba9ed999844c9c3c1bedf2ded")
    ]);
  }
}

class YWHomeProduct extends StatelessWidget {
  final String title;
  final String desc;
  final String imageUrl;
  final titleStyle = TextStyle(fontSize: 20, color: Colors.orange);
  final descStyle = TextStyle(fontSize: 15, color: Colors.blue);

  YWHomeProduct(this.title, this.desc, this.imageUrl);

  @override
  Widget build(BuildContext context) {
    return Container(
        padding: EdgeInsets.all(8),
        decoration:
            BoxDecoration(border: Border.all(color: Colors.purple, width: 8)),
        child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
          Text(title, style: titleStyle),
          SizedBox(height: 8),
          Text(desc, style: descStyle),
          SizedBox(height: 8),
          Image.network(imageUrl)
        ]));
  }
}

五、StatefulWidget的使用

  1. StatefulWidget的使用
    有状态需要改变的时候要使用StatefulWidget
  • StatefulWidget内部有一个抽象方法createState,此方法返回一个State类,继承自StatefulWidget的类需要实现此方法
  • 在自定义的State子类中需要实现build方法生成一个控件
  • StatefulWidget内部不可直接定义状态,但是可以在自定义的State子类中可以定义状态

问题:为什么Flutter在设计的时候,StatefulWidget的build方法放在State中?

  • build出来的widget是需要依赖State中的变量(状态/数据)
  • 在Flutter的运行过程中,widget是不断销毁和创建的,当我们的状态发生改变时,并不希望重新创建一个新的State

  1. 使用StatefulWidget构建一个计数器
    效果图如下:


    其中按钮可以使用ElevatedButton(RaisedButton已废弃)
    使用Column构建竖向组件,Row构建横向组件

import 'package:flutter/material.dart';

main(List<String> args) {
  runApp(MyApp());
}

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

class YWHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(appBar: AppBar(title: Text("购物车")), body: YWHomeContent());
  }
}

class YWHomeContent extends StatefulWidget {
  @override
  _YWHomeContentState createState() => _YWHomeContentState();
}

class _YWHomeContentState extends State<YWHomeContent> {
  int number = 0;
  @override
  Widget build(BuildContext context) {
    return Center(
        child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [
      getButtons(),
      Text("当前计数:$number", style: TextStyle(fontSize: 20))
    ]));
  }

  Widget getButtons() {
    return Row(mainAxisAlignment: MainAxisAlignment.center, children: [
      ElevatedButton(
          child: Text("+", style: TextStyle(fontSize: 20)),
          style: ButtonStyle(
              backgroundColor: MaterialStateProperty.all(Colors.pink)),
          onPressed: () {
            setState(() {
              number++;
            });
          }),
      ElevatedButton(
          child: Text("-", style: TextStyle(fontSize: 20)),
          style: ButtonStyle(
              backgroundColor: MaterialStateProperty.all(Colors.purple)),
          onPressed: () {
            setState(() {
              if (number > 0) {
                number--;
              }
            });
          })
    ]);
  }
}

问题:数值改变能放在setState外面吗?

setState会触发widget build方法重新进行渲染

  1. StatefulWidget传值
    父类给子类传值,传值方式与StatelessWdight语法一致,创建属性(final修饰),实现对应初始化方法,进行赋值,将参数传递给Widget子类
    然后在State类中通过this.widget来实现取值
class YWHomeContent extends StatefulWidget {
  final String message;
  YWHomeContent(this.message);
  @override
  _YWHomeContentState createState() =>_YWHomeContentState();
}

class _YWHomeContentState extends State<YWHomeContent> {
  int number = 0;
  @override
  Widget build(BuildContext context) {
    return Text("${this.widget.message}");
  }
}

这也就是为什么State类定义的泛型需要跟之前创建的StatefulWidget子类保持一致的原因

六、常用Widget

查看Widget组件目录

  1. Text  文本
    1.1  普通文本展示
    • 文本布局参数:如对齐方式TextAlign、排版方向TextDirection、最大行数maxLines、文本超出限制规则overflow、textScaleFactor: 文本缩放因子等,这些都是构造函数参数
    • 控制文本样式的参数:如字体名称fontFamily、 字体大小fontSize、颜色color、文本阴影shadow等,这些都被封装到了构造函数的参数style中
return Center(
    child: Text("调用YWHomeContent的初始化方法",
        textAlign: TextAlign.center,
        maxLines: 1,
        overflow: TextOverflow.ellipsis,
        textScaleFactor: 0.8,
        style: TextStyle(
            fontSize: 30,
            color: Colors.red,
            fontWeight: FontWeight.normal)));

1.2 富文本
富文本使用Text.rich进行创建,必传参数textSpan,可以使用TextSpan进行构造,其内部可以传一个widget,也可以传一个Children数组

return Center(
    child: Text.rich(TextSpan(children: [
  TextSpan(text: "Hello world", style: TextStyle(fontSize: 30)),
  WidgetSpan(child: Icon(Icons.favorite, color: Colors.red)),
  TextSpan(text: "Hello flutter", style: TextStyle(fontSize: 20))
])));

  1. Button 按钮
    2.1 ElevatedButton   (RaisedButton  凸起按钮  ?)
    2.2 TextButton  (FlatButton 平坦按钮  ?)
    2.3 OutlinedButton  边框按钮
    2.4 FloatingActionButton  悬浮按钮
    常用于脚手架Scaffold的入参
    2.5 自定义button  图标文字背景圆角等等

 
TextButton(
      onPressed: () {
        print("TextButton clicked");
      },
      child: Text("TextButton"),
      style: ButtonStyle(
          foregroundColor: MaterialStateProperty.all(Colors.white),
          backgroundColor: MaterialStateProperty.all(Colors.orange)))
OutlinedButton(
      onPressed: () {
        print("OutlinedButton clicked");
      },
      child: Text("OutlinedButton"),
      style: ButtonStyle(
          foregroundColor: MaterialStateProperty.all(Colors.white),
          backgroundColor: MaterialStateProperty.all(Colors.blue)))
FloatingActionButton(
      onPressed: () {
        print("FloatingActionButton clicked");
      },
      child: Icon(Icons.add))
TextButton(
      onPressed: () {
        print("自定义button点击");
      },
      child: Row(
          children: [Icon(Icons.add), Text("添加好友")],
          mainAxisSize: MainAxisSize.min),
      style: ButtonStyle(
          shape: MaterialStateProperty.all(RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(8))),
          foregroundColor: MaterialStateProperty.all(Colors.white),
          backgroundColor: MaterialStateProperty.all(Colors.orange)))
 

  1. Image 图片
    3.1 从网络获取图片 NetworkImage
    通过url链接加载对应图片,
    fit属性控制图片裁切模式,为BoxFit类型,其中fitWidth为宽度固定,自动适配高度;fitHeight为高度固定,自动适配宽度
    repeat属性控制空白部分是否进行图片重复填充,跟fit模式相关
    alignment控制图片裁切完后在视图内展示的位置,可以直接使用宏定义,也可以自定义,Alignment(0, 0)表示居中,值为-1 —— 1
    color和colorBlendMode负责控制颜色混入配置
return Image(
  image: NetworkImage(imageUrl),
  width: 300,
  height: 300,
  fit: BoxFit.contain,
  repeat: ImageRepeat.repeatY,
  alignment: Alignment(1, 1),
  color: Colors.pink,
  colorBlendMode: BlendMode.color,
);

简写模式如下:

Image.network(imageUrl)

问题:(-1,-1)代表什么位置?
问题: 如何设置图片占位图?


3.2 从本地获取图片
步骤如下:

    • 在flutter项目中创建一个文件夹,用于存储图片
      1x图片放到指定文件夹内,如果有2x、3x图片,在1x图片所在文件夹内建立2.0x文件夹、3.0x文件夹放置
    • 在pubspec.yaml进行配置
      找到assets:配置处,将注释取消掉
      添加对应图片路径配置 配置完成后执行下flutter packages get重新获取依赖
assets:
- assets/Images/
    • 使用图片
return Image(image: AssetImage("assets/Images/001.jpg"));

3.3 实现圆角头像

    • 使用CircleAvatar组件
return CircleAvatar(
    backgroundImage: AssetImage("assets/Images/001.jpg"),
    radius: 50,
    child: Container(
    alignment: Alignment(0, 0),
    width: 100,
    height: 20,
    child: Text("兵长利威尔")));

其中backgroundImage传入抽象类ImageProvider图片,radius为半径,child为内部widget

    • 使用ClipOval组件
ClipOval(
      child: Image(
    image: NetworkImage(imageUrl),
    width: 100,
    height: 100,
    fit: BoxFit.cover,
  ))

3.4 实现圆角图片

    • ClipRRect
ClipRRect(
      borderRadius: BorderRadius.circular(80),
      child: Image.network(imageUrl,
          width: 160, height: 160, fit: BoxFit.cover))

七、StatelessWidget、StatefulWidget生命周期

  1. 生命周期的作用(意义)
  • 初始化一些数据、状态、变量
  • 发送网络请求时机
  • 进行一些事件的监听
  • 管理内存(手动销毁)

  1. StatelessWidget生命周期
    这里比较简单,只有两个生命周期
  • 构造函数被调用
  • 调用build方法

class TestWidget extends StatelessWidget {
  TestWidget() {
    print("构造函数被创建");
  }

  @override
  Widget build(BuildContext context) {
    print("build方法被调用");
    return Container();
  }
}

  1. StatefulWidget生命周期

  • 第一步:调用StatefulWidget子类的构造方法
  • 第二步:调用StatefulWidget子类的createState方法
  • 第三步:调用State子类的构造方法
  • 第四步 调用State子类的initState方法
    用于状态的初始化,会在State类完成构造之后,build方法执行之前,进行执行
    initState方法使用@mustCallSuper标记,必须调用父类initState方法
  • 第五步:执行State子类的build方法
  • 最后,当前的Widget子类不再使用时,会执行State子类的dispose方法,进行内存的释放

此外:

  • didChangeDependencies方法  在initState方法执行后,或者从其他对象中依赖一些数据发生改变时,比如inheritedWidget,会执行此方法
  • didUpdateWidget方法  当重新创建Widget子类(rebuild),会触发state子类的didUpdateWidget方法

代码如下所示:

class YWHomeContent extends StatefulWidget {
  YWHomeContent() {
    print("1.调用YWHomeContent的初始化方法");
  }
  @override
  _YWHomeContentState createState() {
    print("2.调用YWHomeContent的createState方法");
    return _YWHomeContentState();
  }
}

class _YWHomeContentState extends State<YWHomeContent> {
  _YWHomeContentState() {
    print("3.调用_YWHomeContentState的初始化方法");
  }

  @override
  void initState() {
    super.initState();
    print("4.调用_YWHomeContentState的initState方法");
  }

  @override
  void didChangeDependencies() {
    print("调用_YWHomeContentState的didChangeDependencies方法");
    super.didChangeDependencies();
  }

  @override
  void didUpdateWidget(covariant YWHomeContent oldWidget) {
    print("调用_YWHomeContentState的didUpdateWidget方法");
    super.didUpdateWidget(oldWidget);
  }

  @override
  Widget build(BuildContext context) {
    print("5.调用_YWHomeContentState的build方法");
    return Text("Hello World");
  }

  @override
  void dispose() {
    super.dispose();
    print("6.调用_YWHomeContentState的dispose方法");
  }
}

  • setState方法会在内部触发重新运行build方法,根据最新的状态返回新的控件,所以状态的修改需要在setState方法中进行

  1. StatefulWidget生命周期的复杂版
    在StatefulWidget普通生命周期的基础上,还有一些复杂的过程未提及到

  • mounted
  • dirty state & clean state
    疑问:意义及用法?
Flutter从0到1构建大前端应用(三):Flutter基础 文章目录前言 前言 阅读详情

相关推荐

Waymo数据集里的隐藏彩蛋:5个激光雷达数据融合实战(附Python代码)

本文深入解析Waymo数据集中5个激光雷达的数据融合技术,提供Python实战代码,帮助开发者掌握多传感器协同工作的关键方法。通过时间同步、坐标转换和运动补偿等技术,实现高精度3D场景重建,提升自动驾驶系统的环境感知能力。

weixin_30399821的博客 75

Flutter 3.3.6 中FlatButton, RaisedButton, & OutlineButton找不到

FlatButton,, and这三个widget 已经有了新的控件替代,并且有新的主题做对应的替换即可// ...);// ...);// ...);

闪亮的大早的博客 8218

RLHF的数学表示

RLHF(Reinforcement Learning with Human Feedback)是一种结合了强化学习和人类反馈的机器学习方法。它通常用于训练智能体(agent)在复杂环境中做出决策,同时利用人类的反馈来指导和改进学习过程。RLHF 没有一个统一的数学表示式,因为它依赖于具体的应用场景和实现细节。然而,我们可以从强化学习和人类反馈的角度来描述RLHF的一些关键数学概念。

xw555666的博客 684

Flutter学习日记之各种按钮的使用

本文地址:https://blog.csdn.net/qq_40785165/article/details/117457267,转载需附上此地址 大家好,我是小黑,一个还没秃头的程序员~~~ 奋斗的意义,不在于,一定会让你取得多大的成就,只是让你在平凡的日子里,活得比原来的那个自己,更好一点。 今天分享的内容是Flutter的表单组件中的各种按钮的使用,源码地址:https://gitee.com/fjjxxy/flutter-study.git,效果如下: 今天介绍的按钮有以下几个: RaisedB

qq_40785165的博客 1936

零基础小白Coze知识普及【新手必备资料!!】

AI智能体|扣子(Coze)工作流搭建【零基础小白Coze知识普及】 1、领取100+工作流源码!复制到扣子即可直接使用 2、AI认知+9节商业智能体拆解 3、500+各行业高质量提示词 4、超低价格使用即梦文生图图生视频和banana生图

Zhima0522的博客 3243

AI安全攻防:十六进制编码与表情符号如何绕过ChatGPT安全限制

在人工智能安全领域,提示词工程是影响大语言模型行为的关键技术。其核心原理在于通过精心设计的输入文本,引导模型生成特定内容或执行特定任务。这项技术的价值在于能够深入探究模型的理解机制与决策边界,对于模型优化、安全测试及功能开发具有重要意义。在实际应用场景中,研究人员常利用编码转换、符号插入等方法构造输入,以测试模型安全护栏的鲁棒性。近期,一种结合十六进制编码与表情符号的组合攻击手法受到关注,该方法通过信息伪装与语义干扰,试图绕过模型内置的内容过滤机制,这凸显了当前AI安全在输入预处理与语义理解协同防御上面临的

weixin_30633405的博客 441

flutter 切换tab的会重新build的解决方案

flutter 切换tab的会重新build的解决方案 当我们用如下方式创建tab时 _onTabClick(int index){ _currentIndex=index; setState(() { }); } @override Widget build(BuildContext context) { return Scaffold( appBar: _currentIndex==0?null:AppBar( center

qls1191的博客 1476

第一篇:常见CAN错误帧及其排查方向

在本文中主要阐述各类错误帧的形成原因以及在使用同星硬件设备出现错误帧时,应当 如何进行排查并消除错误帧。在 CAN 总线通信中,通常遇见的错误帧主要为以下五种,其 分别是:bit error、ACK error、stuff error、CRC error 以及 form error。

u013089100的博客 1723

Flutter中如何限制widget重新build

文章目录一、演示程序介绍二、使用缓存变量处理重新build的问题三、使用const处理重新build问题 一、演示程序介绍 有时候在开发中会出现多次build的情况,通常没什么问题,但是偶尔会导致数据重新初始化,这样就比较麻烦,所以以下给出几种解决重新build问题的方式。首先来看一个简单的没有处理的代码: import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends Stat

Mr_Tony的专栏 1764

【原理图PCB专题】原理图图纸锁定/解锁与PCB文件加密方式

在工作中我们会遇到需要冻结原理图进行评审和加密图纸防止被他人盗用的需求。那么在OrCAD Capture中如何对图纸进行锁定与解锁,如何在Allegro中对PCB工程进行加密呢?

一点硬件 3245

【AI智能体】最强AI编程利器 Claude Code 从部署到项目实战详解

最强AI编程利器 Claude Code 从部署到项目实战详解

congge 4501

flutter中Navigator.push路由跳转导致的重复build问题,妥协解决方法。。

我的是在SliverList中给Container外面包的GestureDetector,结果路由跳转会rebuild整个SilverList。。 导致内存飙升,跳转动画会卡顿一下, 后来用get包去路由跳转,没出现rebuild的问题。 GET包 : https://pub.dev/packages/get dependencies: get: ^1.6.3 event: eventsEn...

qq_26014709的博客 3778

[SystemC]SystemC中的模块和程序

SystemC 中的层次结构是使用类 sc_module 创建的。sc_module 可以直接使用,也可以使用宏 SC_MODULE “隐藏”。上面的示例 SC_MODULE 创建了一个名为 nand2 的 sc_module 类对象。它的输出纯粹是输入值的函数。因此,模型可以使用最简单的 SystemC 进程,即 SC_METHOD。摘要:本节包含一个完整的简单设计,用于演示 SystemC 中模块和流程的使用。同样,重要的是要注意这不是典型的设计风格 - 但它很好而且易于理解。为什么要看模块和流程?

元直的博客 1863

【flutter】flutter基础总结1

假设我们有个http请求,当然很耗时,就需要用异步执行此任务。注意,在dart中执行异步任务,需要使用await和async关键词。await用于修饰调用方法,async则在调用方法名后添加。application interface,一般返回服务器的数据,数据格式有很多。所以需要我们和服务器开发人员商量好。本例,我们返回json格式。获取方式参考上面的方法。

cdkd123的专栏 790

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Flutter基础(项目1结构)

【代码】Flutter基础(结构)

hongsegeming的博客 124

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Flutter1.0入门基础

Flutter1.0入门基础 注:原课程视频是基于Flutter1的; 目标: 开发入门:工具、环境搭建、入门必备 开发技巧:导航框架、常用功能 开发流程:网络、数据存储、列表、Flutter与Native混编 工程封装:模块开发、AI结合 项目上手:包和插件的开发、屏幕适配和兼容、打包与发布、Flutter的升级和适配; 导航框架实现:Scaffold+PageView 服务端交互:http 页面路由跳转:Navigator 监听列表滚动:NotificationListener 自定义组件 封装

baby_hua的专栏 1238

Flutter基础总结1

时间:2020/8/30 1.main函数--入口函数 void main() =>runApp(MaterialApp()) MaterialApp()的构造方法里面包含很多的参数: MaterialApp({ Key key, this.title = '', // 设备用于为用户识别应用程序的单行描述 this.home, // 应用程序默认路由的小部件,用来定义当前应用打开的时候,所显示的界面 this.color, // 在操作系统界面中应用程序使用的主色。

仁亮的开发小屋 281

【Flutter -- 基础】快速入门 Flutter_flutter开发零基础入门(1)

Flutter app 使用了 Dart 语言,源自于 Google,现在是 ECMA 的标准。Dart 吸收了许多现代语言的特性,比如 Kotlin 和 Swift,同时能被转译成 js 代码。作为一个跨平台框架,Flutter 和 React Native 非常像,因为 Flutter 支持响应式和声明式语法。但和 React Native 不同,Flutter 不需要 Javascript 桥接,这显著提升了 app 的加载时间和整体性能。Dart 是通过 AOT 编译来做到这一点的。

2401_84520332的博客 725

Flutter-基础组件1

所有组件翻译自官方文档 https://docs.flutter.io/flutter/widgets/widgets-library.html 一、Container 一个拥有绘制、定位、调整大小的 widget。 容器首先由decoration中定义的边界属性围绕子widget,然后对填充范围应用附加约束(将宽度和高度合并为约束,如果非空的话)。 然后容器被margin属性设置的空隙边缘包...

Chuck Chan的专栏 387

Flutter 升级 1,android开发基础有哪些

今天关于面试的分享就到这里,还是那句话,有些东西你不仅要懂,而且要能够很好地表达出来,能够让面试官认可你的理解,例如Handler机制,这个是面试必问之题。有些晦涩的点,或许它只活在面试当中,实际工作当中你压根不会用到它,但是你要知道它是什么东西。最后在这里小编分享一份自己收录整理上述技术体系图相关的几十套腾讯、头条、阿里、美团等公司2021年的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。还有。

2401_84149444的博客 740

Flutter基础篇(1)-- AndroidStudio中配置Flutter插件

1:前言 Flutter是谷歌的移动UI框架,可以快速在iOS和Android上构建高质量的原生用户界面。 Flutter可以与现有的代码一起工作。在全 世界,Flutter正在被越来越多的开发者和组织使用,并且Flutter是完全免费、开源的。(这句话有点熟悉哈 ~ ~) 应用程序是用Dart语言编写的,无需移动开发经验即可开始使用。Flutter 基于底层skia直接渲染,整个框架的中心...

沐沐的博客 1万+

Flutter基础控件小结1

1.Text Image Icon SelectableText :可以让人复制的文字(双击就有反应了) Checkbox:多选勾选框使用: 需要在外面建立一个变量isChecke Radio:排他性选择框2选一个不能选另一个 class _studyState extends State<study> { bool isChecked = false; int _sex = 0;//设置一下 @override Widget build(BuildContext cont

qq_40156884的博客 396

flutter面试题——基础篇(1)

Dart本身是单线程模型。在单线程中是以消息循环机制来运行的,其中包含两个任务队列,一个是“微任务队列” microtask queue 另一个是“事件队列” event queue。main():不可变的UI配置(如:Widget的实例化对象,管理生命周期和树结构。:负责布局和绘制(如尺寸、位置计算)。

m0_65035198的博客 1388

Flutter1:基础--安卓手机调试

注意安装完成后,需要打开android studio 安装插件。新建flutter项目,注意选择flutter sdk位置。加入path:D:\src\flutter\bin。在studio安装手机对应的SDK。

rapid2011的专栏 3187

Flutter StatelessWidget与基础组件(1.1)

StatelessWidget与基础组件ContainerTextIconCloseButtonBackButtonChipDividerCardAlertDialog Container 容器组件,继承自StatelessWidget Container参数 类型 说明 key Key Container 唯一标识符,用于查找更新 alignment Alignment 控制Container的对齐方式 padding EdgeInsets EdgeInsets.only(l.

高级开发者进阶ing... QaQ 588

Flutter笔记_基础篇(1)

这是之前在入手flutter时做的笔记,由于笔记是使用幕布来记录的,幕布不支持markdown格式,所以在幕布上的笔记基本都很少会去整理,这次用了pandoc工具将幕布的笔记转为markdown格式,无奈支持很不良好,基本还是得手动来整理,所以这一篇也整理了一半,没办法 太浪费时间 放弃了,就贴个笔记的幕布链接吧。本篇主要了解下移动端技术,原生和跨平台技术进行对比 本篇主要记录学习 “Flutter实战” 一书的笔记: https://book.flutterchina.club/chapter1/mo

追求,成长 718
上一篇: dart基础语法(4)
下一篇: 写给我自己的2022
怀化纱厂球迷
博客等级 码龄14年 1329粉丝 179原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值