StatelessWidget与StatefulWidget简介
我们需要创建我们自定义的Widget控件,只需要创建一个类去继承StatelessWidget
和StatefulWidget
这两个类即可,这两个类都是Flutter提供的基本Widget类,不过在使用上有所区别
StatelessWidget
是静态Widget,而StatefulWidget
则是动态Widget
StatefulWidget
与StatelessWidget
唯一不同的特点,就是其提供了一个setState()
的方法,我们可以调用此方法,更新数据,从而会让该Widget的内容发生改变(本质上与MVVM模式类似)
那什么是静态Widget和动态Widget分别是什么意思呢?静态Widget则是说明其中的内容不会发生改变,如Button按钮、文字Text等,动态Widget则是内容是可变的,如一个列表显示的数据,其数据是通过网络请求来获得的,网络请求返回的数据每次可能有所不一样,之后我们需要增加一个下拉刷新的效果,我们就可以调用setState的方法,去更改数据,从而进一步改变列表中显示的数据
综上所述:我们需要创建自定义Widget,需要根据需求来判断是应该使用
StatefulWidget
还是StatelessWidget
,不过实际的需求一般都是动态的多些,比如说两个下拉框需要数据联动,或者是复选框的勾选等...
下面就是分别介绍StatefulWidget和StatelessWidget这两种Widget的用法
StatelessWidget
创建Widget
这种Widget实现比较简单,我们只需要定义一个类,继承StatelessWidget
,之后实现StatelessWidget
的build接口方法即可
class DemoWidget extends StatelessWidget{
@override
Widget build(BuildContext context) {
return new MaterialApp(
theme: new ThemeData(
primaryColor: Colors.blue,
accentColor: Colors.blueAccent,
),
home: new Scaffold(
appBar: new AppBar(
title: new Text('Flutter Bar'),
),
body: new Center(
child: new Text('Hello World'),
),
floatingActionButton:
FloatingActionButton(onPressed: () {
Fluttertoast.showToast(
msg: "点击添加",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
backgroundColor: Colors.black,
);
},
child: Icon(Icons.add)
),
),
);
}
我这里是直接把之前的那个例子拿过来用了,把它封装成了DemoWidget
使用
使用的话就很简单了,我们直接new一个DemoWidget类对象即可
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
//new关键字可以省略
return DemoWidget();
}
}
StatefulWidget
简单说明
StatefulWidget实现过程稍微复杂一些,需要两个类,一个是Widget,另外一个则是State状态类,如下图所示
还记得之前说到的setState方法吗,其实它是State状态类里的方法
StatefulWidget
与StatelessWidget
不一样,StatefulWidget
需要实现createState()
方法,其方法需要返回一个State
对象,而State
类与之前的StatelessWidget
一样,需要实现build()
方法
之后,每当调用setState()
方法时候,DemoWidget就会得到一个新的状态,并重新渲染页面(也就是改变了页面显示的内容)
class DemoWidget extends StatefulWidget{
@override
State<StatefulWidget> createState() {
return DemoWidgetState();
}
}
class DemoWidgetState extends State<DemoWidget>{
@override
Widget build(BuildContext context) {
return new MaterialApp(
theme: new ThemeData(
primaryColor: Colors.blue,
accentColor: Colors.blueAccent,
),
home: new Scaffold(
appBar: new AppBar(
title: new Text('Flutter Bar'),
),
body: new Center(
child: new Text('Hello World'),
),
floatingActionButton:
FloatingActionButton(onPressed: () {
Fluttertoast.showToast(
msg: "点击添加",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
backgroundColor: Colors.black,
);
},
child: Icon(Icons.add)
),
),
);
}
}
PS:用法和之前一样,直接创建个实例对象即可显示页面
改变页面数据
上面的代码其实与之前的StatelessWidget中的代码效果一致,点击按钮会弹出Toast提示,接下来我们对上面的代码进行部分的改造,实现点击按钮,让页面中间显示的数据发生改变,我们只需要改DemoWidgetState这个类中的代码即可
class DemoWidgetState extends State<DemoWidget> {
var i = 0;
var str = "hello";
@override
Widget build(BuildContext context) {
return new MaterialApp(
theme: new ThemeData(
primaryColor: Colors.blue,
accentColor: Colors.blueAccent,
),
home: new Scaffold(
appBar: new AppBar(
title: new Text('Flutter Bar'),
),
body: new Center(
child: new Text(str),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
str = "hello$i";
i++;
});
},
child: Icon(Icons.add)),
),
);
}
}
可以看到我们需要的效果,点击添加按钮,中间的文字就会变为hello0
,之后第二次就变为hello1
使用补充
1.传递参数
上面为StatefulWidget的基本用法,接下来补充一下如何传递参数以及获取布局里的数据
传递参数稍微有些繁琐,需要在Widget中写一个变量,同时,也需要在State状态类中写个变量,比如之前的那个布局,我们中间默认显示hello,之后点击按钮会变为hello0
我们想要实现创建的时候直接给定默认显示的数据,可以是hello,或者是其他的数据,就可以写个构造函数,用来传递默认显示的数据即可,代码如下图所示:
可以看到,代码其实没有较大的改动,只是在Widget和State这两个类中添加了对应的成员变量和构造方法
2.外层Widget改变当前Widget
这里可能起的名字不是很好,我们举个例子来说明一下
比如我们有个页面,有个按钮Button的Widget和我们创建的自定义Widget,我们想要实现点击按钮就要获得我们自定义Widget里的数据,这个时候我们有什么办法呢?
我不确定我这是不是正确的解决方法,我的做法是,在Widget类中声明了一个State的变量引用,之后由State类中提供一个方法,用来修改数据
之后使用的时候,我们可以直接调用DemoWidget对象实例的state变量,从而在调用setData()
当然,你也可以在DemoWidget中创建一个方法,之后在里面调用state的方法,如:
又或者state不写那个setData方法,直接在Widget中写也可以,如:
PS:至于获取Widget的数据,与上面也是类似,直接在Widget或者是State中定义个方法,用来返回数据即可
评论区