在Flutter中,组件的状态管理还是非常重要的,组件要么是无状态的组件,要么是有状态的组件。无状态的组件使用起来似乎并不复杂,有状态的组件又是怎么管理的呢?这里就谈一谈 StatefullWidget 与 State 对组件状态的管理。状态管理又可以分为三类:自己管理,父组件管理,父子组件混合管理。
第一种自己的状态自己管理,是最简单的一种,看代码;
import 'package:flutter/material.dart';
//自己的状态自己管理,继承StatefulWidget
class SelfManageStatus extends StatefulWidget{
@override
State<StatefulWidget> createState() {
return _SelfManageStatusState();
}
}
//状态类,一个StatefulWidget 对应一个 State
class _SelfManageStatusState extends State<SelfManageStatus>{
//点击次数,默认 0
int clickNum = 0;
//点击事件
void doClick(){
// 状态由调用setState()管理
setState(() {
// 每次点击加 1
clickNum++;
});
}
/// 构建控件元素
@override
Widget build(BuildContext context) {
// 使用GestureDetector监测手势相关事件
return GestureDetector(
onTap: doClick,
child: Container(
child: Center(
child: Column(
children: <Widget>[
Text(
"自己管理,点我呀",
style: TextStyle(fontSize: 18,color: Colors.yellow),
),
Text("点击次数:$clickNum"),
],
)
),
//宽度,double.infinity:百分之百
width: double.infinity,
height: 100,
color: Colors.red
),
);
}
}
说明:通过这个demo可以看出,StatefulWidget 与 State 的使用是一一对应的,状态管理交由 State 处理;手势在手机屏幕上滑动通过 GestureDetector类检测,状态的管理通过 State 类的 setState() 方法控制。把 setState() 这个方法去掉,就做不到状态的保持。
第二种情况,父组件管理;
//父管理子状态,父组件继承StatefulWidget
class ParentManageStatus extends StatefulWidget{
@override
State<StatefulWidget> createState() {
return _ParentManageStatusState();
}
}
//父组件状态
class _ParentManageStatusState extends State<ParentManageStatus>{
//点击次数,默认0
int clickNum = 0;
//当数量发生改变时,由父组件调用setState()管理状态
void handleClick(int num){
setState(() {
//每点击一次加num,该num由子组件传递过来
clickNum+=num;
});
}
@override
Widget build(BuildContext context) {
return Container(
child: ChildArea(
clickNum : clickNum,
numChanged : handleClick,
),
);
}
}
//子组件继承StatelessWidget无状态组件
class ChildArea extends StatelessWidget{
//不可改变的点击数量
final clickNum;
//状态的传递
final ValueChanged<int> numChanged;
ChildArea({this.clickNum, required this.numChanged});
//点击事件
void doClick(){
/// 没有去管理状态,交由父类管理
numChanged(1);
}
@override
Widget build(BuildContext context) {
// 使用GestureDetector监测手势相关事件
return GestureDetector(
// 点击事件监听
onTap: doClick,
child: Container(
child: Center(
child: Column(
children: <Widget>[
Text(
"子组件父管理,点我呀",
style: TextStyle(fontSize: 18,color: Colors.yellow),
),
Text("点击次数:$clickNum"),
],
)
),
width: double.infinity,
height: 100,
color: Colors.green
),
);
}
}
说明:子组件继承 StatelessWidget 无状态组件,对组件的状态无需管理,监听到点击事件时,将状态交由父组件管理,父组件管理后再传递过来回显。父组件管理就是一个有状态的组件和无状态的组件的结合。
第三种情况,状态混合管理;
import 'package:flutter/material.dart';
//父子状态混合管理,父组件
class HybridManageStatus extends StatefulWidget{
@override
State<StatefulWidget> createState() {
return _HybridManageStatusState();
}
}
//父组件状态
class _HybridManageStatusState extends State<HybridManageStatus>{
// 子点击次数
int clickNum = 0;
// 父点击次数
int pclickNum = 0;
//点击事件,调用setState()进行状态保持
void handleClick(int num){
setState(() {
clickNum = num;
pclickNum++;
});
}
//点击事件,调用setState()进行状态保持
void doClick(){
setState(() {
pclickNum++;
});
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: doClick,
child: Container(
child: Center(
child: Column(
children: <Widget>[
ChildStatus(
clickNum: this.clickNum,
numChanged: handleClick,
),
Text(
"混合管理,我是父组件里的控件",
style: TextStyle(fontSize: 18,color: Colors.yellow),
),
Text("子点击次数:$clickNum,父点击次数:$pclickNum"),
],
),
),
width: double.infinity,
height: 200,
color: Colors.grey
),
);
}
}
//子组件
class ChildStatus extends StatefulWidget{
final clickNum;
final ValueChanged<int> numChanged;
ChildStatus({this.clickNum, required this.numChanged});
@override
State<StatefulWidget> createState() {
return _ChildStatusState();
}
}
//子组件状态
class _ChildStatusState extends State<ChildStatus>{
int clickNum = 0;
void doClick(){
setState((){
clickNum++;
});
widget.numChanged(clickNum);
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: doClick,
child: Container(
child: Center(
child: Column(
children: <Widget>[
Text(
"混合管理,我是父组件里的子组件控件,点我呀",
style: TextStyle(fontSize: 18,color: Colors.yellow),
),
Text("点击次数:$clickNum"),
],
)
),
width: double.infinity,
height: 100,
color: Colors.blue,
),
);
}
}
说明:
- 混合管理,父组件是有状态的组件,子组件也是有状态的组件,是两个有状态组件的结合,子组件状态的变更会通知父组件(最重要的一点)。混合管理对于新手来说,还是有点复杂的,但也是使用频率最多的状态管理,所以必须熟练掌握。
2.这个demo里,在父组件里又单独加了一个组件,作为参照,父组件包含子组件,但是父组件的控件在子组件范围外,子组件以外的父组件只受父组件的影响,和子组件无关。
代码写完了,将这三种状态整合起来
import 'package:flutter/material.dart';
import 'OneArea.dart';
import 'ThreeAreaParent.dart';
import 'TwoAreaParent.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: Text("welocom to flutter"),
),
body: Center(
child: ThreeState(),
),
),
);
}
}
//继承无状态组件,整合三种状态的组件
class ThreeState extends StatelessWidget{
@override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
OneArea(),
TwoAreaParent(),
ThreeAreaParent()
],
)
);
}
}
运行代码,每一块各点击三下,确认统计数字是否正确;

网友评论