一.Flutter Widget
在 Flutter 中一切的显示都是 Widget ,Widget 是一切的基础,利用响应式模式进行渲染。在 Flutter 中自定义组件其实就是一个类,这个类需要继承 StatelessWidget\StatefulWidget
。
Widget 分为 有状态(StatefulWidget) 和 无状态(StatelessWidget) 两种,在 Flutter 中每个页面都是一帧,无状态就是保持在那一帧,而有状态的 Widget 当数据更新时,其实是创建了新的 Widget,只是 State 实现了跨帧的数据同步保存。
二.无状态StatelessWidget
1.定义
如果一个控件的UI页都是静态的,也就是说说就是一旦这些UI页被成功渲染之后就不需要也不可能去改变他的状态,就是一开始是什么样就是什么样,在UI上没有任何的变化,例如纯展示页面。就使用StatelessWidget。
在需要实现一个StatelessWidget组件的时候,声明一个class类StateLessDemo需要通过extends继承StatelessWidget,必须要重写 build 方法,这个 build 方法会携带一个 BuildContext 参数。另外 build 方法返回一个 Widget 值,也就是我们自定义的无状态的布局。这样就可以创建一个无状态的Widget。这个Widget创建完成后,Widget的状态就固定了,当前Widget就是一个无状态的,当前Widget的内容固定,不可更改。StatelessWidget 的 构造方法 和 build 方法之会创建一次,不会随着子节点StatefulWidget 控件的状态改变而重构布局。 所以它适合放在布局嵌入比较深的布局节点,因为StatelessWidget是静态的,所以性能比较好,建议多使用。
注意: 如果无状态Widget里面有子Widget,并且子Widget是有状态的,则子Widget的内容是可以通过setState来更改的。无状态Widget影响的仅仅是自己是无状态的,不回影响他的父Widget和子Widget。
2.使用
flutter系统中提供了许多的已经定义好的StatelessWidget,例如StatelessWidget:StatelessWidget、 Icon、 IconButton、Text等。
class CircleAvatar extends StatelessWidget {}
class Icon extends StatelessWidget {}
class Text extends StatelessWidget {}
class IconButton extends StatelessWidget {}
Widget 和 Widget 之间通过 child: 进行嵌套。其中有的 Widget 只能有一个 child;有的 Widget 可以多个 child ,也就是children,比如` Column 布局。
StatelessWidget 是不能调用setState函数的。
例如:
class HomePage extends StatelessWidget {
int countNum = 1;
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
SizedBox(height: 200),
Text("${ this.countNum }"),
SizedBox(height: 20),
RaisedButton(
child: Text("按钮"),
onPressed: (){
// setState() // 错误写法 没法改变页面里面的数据
this.countNum++;
print(this.countNum);
}
)
]
);
}
}
三.有状态StatefulWidget
1.定义
StatefulWidget是可变状态的widget。即StatefulWidget依赖的数据在Widget生命周期中可能会频繁的发生变化。使用setState方法管理StatefulWidget的状态的改变它是数据驱动视图更新的关键函数。调用setState函数时,会通知Flutter框架某个状态发生了变化,Flutter会重新运行build方法,应用程序变可以显示最新的状态,Widget只是视图的“配置信息”,是数据的映射。
2.使用
Checkbox, Radio, Slider, InkWell, Form, 和 TextField 都是有状态的widget,也是StatefulWidget的子类。
class Checkbox extends StatefulWidget {}
class Radio<T> extends StatefulWidget {}
class Slider extends StatefulWidget {}
使用 StatefullWidget 情况
class HomePage extends StatefulWidget {
HomePage({Key key}) : super(key: key);
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
int countNum = 0;
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
SizedBox(height: 200),
Chip(
label:Text('${this.countNum}') ,
),
SizedBox(height: 20),
RaisedButton(
child: Text('按钮'),
onPressed: (){
setState(() { // 只有有状态组件里面才有
this.countNum++;
});
}
)
]
);
}
}
3.State 的生命周期
如下代码:
import 'dart:async';
import 'package:flutter/material.dart';
class DemoStateWidget extends StatefulWidget {
final String text;
////通过构造方法传值
DemoStateWidget(this.text);
///主要是负责创建state
@override
_DemoStateWidgetState createState() => _DemoStateWidgetState(text);
}
class _DemoStateWidgetState extends State<DemoStateWidget> {
String text;
_DemoStateWidgetState(this.text);
@override
void initState() {
///初始化,这个函数在生命周期中只调用一次
super.initState();
///定时2秒
new Future.delayed(const Duration(seconds: 1), () {
setState(() {
text = "这就变了数值";
});
});
}
@override
void dispose() {
///销毁
super.dispose();
}
@override
void didChangeDependencies() {
///在initState之后调 Called when a dependency of this [State] object changes.
super.didChangeDependencies();
}
@override
Widget build(BuildContext context) {
return Container(
child: Text(text ?? "这就是有状态DMEO"),
);
}
}
State 中主要的声明周期有 :
- initState :初始化,理论上只有初始化一次,第二篇中会说特殊情况下。
- didChangeDependencies:在 initState 之后调用,此时可以获取其他 State 。
- dispose :销毁,只会调用一次。
只要关注在:创建你的 StatelessWidget 或者 StatefulWidget 而已。你需要的就是在 build 中堆积你的布局,然后把数据添加到 Widget 中,最后通过 setState 改变数据,从而实现画面变化。
网友评论