本篇文章介绍一下
Stateful
状态的Widget,如何初始化,如何刷新的,在使用的过程中应该如何正确的使用。
来一个看起来和初始化工程很像的代码:
import 'package:flutter/material.dart';
class BoxCounterDemo extends StatefulWidget {
@override
// _BoxCounterDemoState createState() => _BoxCounterDemoState();
// 上面代码和下面的效果一样
State<StatefulWidget> createState() {
return _BoxCounterDemoState();
}
}
class _BoxCounterDemoState extends State<BoxCounterDemo> {
int countNumber = 0;
TextStyle _style = TextStyle(
color: Colors.red,
fontSize: 56
);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('BoxStateFulDemo'),
),
body: Center(
child: Text('$countNumber',style: _style,),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: (){
countNumber += 1;
setState(() {});//重新刷新! 这一句非常重要
print('count = $countNumber');
},
),
);
}
}
先看一下执行效果,再细细说明:
在前面的文章里已经提到过,只有继承
StatefulWidget
的部件,才有刷新的功能,那么StatefulWidget的部件是如何刷新啊,当部件收到setState(){}
的调用时Flutter 会重新调用其对应 State 的 build
方法来重新构造 Widget Tree
,Flutter 获取到最新的 Widget Tree 后会与当前的 Widget Tree 做对比,绘制不一样的地方,flutter的渲染机制用的是skia,和web的渲染是一样的,具有轻量化和快速的特点。在Flutter中,Widget采用的是React风格,
StatefulWidget
类型的部件是将Widget和State写在了两个类中,extends State<T>
后面需要指明该State对应的Widget是哪个,之所以要写进2个类里面,是和他们的生命周期有关。Widget
相当于时一个暂时的对象,只是为了展示和布局当前状态时用的,只要状态发生了改变,就会失效,而State
可以说是永久的,它里面存储了一些必要信息,每次状态改变后,通过比较,只更新和修改差异化的东西。下面来一个带有事件传递,并且含有Stateles的部件代码示例:
class _ChildLessWidget extends StatelessWidget { //stateless
final bool active;
final ValueChanged<bool> onChanged;
_ChildLessWidget({Key key, this.active: false, @required this.onChanged})
: super(key: key);
void _handleTap() {
onChanged(!active);
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: _handleTap,
child: Container(
alignment: Alignment(0, 0),
child: Text(
'点击更改背景色',
style: new TextStyle(fontSize: 44.0, color: Colors.white),
),
color: active ? Colors.red : Colors.blue,
),
);
}
}
class BoxParentWidget extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _BoxParentWidgetState();
}
}
class _BoxParentWidgetState extends State<BoxParentWidget> {
var _active = false;
_handleDidTap(bool newValue) {
setState(() {
_active = newValue;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('BoxStateFulDemo'),
),
body: _ChildLessWidget(
active: _active,
onChanged: _handleDidTap,
),
);
}
}
运行效果是这个样子:
BoxParentWidget
是一个Stateful
类型的部件,内部含有一个Stateless
类型的部件但是我们要想在stateless类型的部件里如何把一个事件传递出来,然后通知Stateful
类型的部件需要刷新了,所以我们在_ChildLessWidget
的构造函数中将一个Bool值和点击事件进行传递进去,在里面接收后,使用了GestureDetector
组件的点击调用私有方法_handleTap
,然后触发传参进去的事件onChanged
,这样就回调出来进行_handleDidTap
的方法调用setState
方法的调用。
在后面的开发中会经常用到Widget的状态管理,这里只是简单介绍了一下,相信在后面使用的过程中,我们会掌握越来越多的使用技巧。所有的代码都可以在Github:BoxJ/Flutter-daydayup中下载,本篇代码的文件夹是
boxdemo_004
,欢迎一起交流!