1、简介
1、状态管理的方式
1、父 Widget 管理 Widget 状态。(推荐)
2、Widget 管理自己的状态。
3、混合管理(父 Widget 和 Widget 都管理状态)。
2、状态管理的原则
1、如果状态是用户数据,如复选框的选中状态、滑块的位置,则该状态最好由父 Widget 管理。
2、如果状态是有关界面外观效果的,例如颜色、动画,那么状态最好由 Widget 本身来管理。
3、如果某一个状态是不同 Widget 共享的则最好由它们共同的父 Widget 管理。
2、示例
要求:
1、屏幕中间有一个方块;
2、默认背景色为绿色;宽和高都是 200;中间有文字为 Active,文字大小为 32,颜色为白色;
3、点击方块后,背景色为灰色,中间文字为 Inactive,文字颜色为黑色,其他不变;
注:需要使用手势事件的 widget GestureDetector。
1、父 Widget 状态管理
import 'package:flutter/material.dart';
//sup class
class SupBoxClass extends StatefulWidget {
const SupBoxClass({super.key});
@override
State<SupBoxClass> createState() => _SupBoxClassState();
}
class _SupBoxClassState extends State<SupBoxClass> {
bool _active = false;
void _tapAction(bool value){
setState(() {
_active = value;
});
}
@override
Widget build(BuildContext context) {
return Center(
child: SubBoxClass(
active: _active,
onValueChanged: _tapAction
),
);
}
}
//sub class
class SubBoxClass extends StatelessWidget {
const SubBoxClass({required this.active,required this.onValueChanged,super.key});
final bool active;
final ValueChanged<bool> onValueChanged;
void _handleTap(){
onValueChanged(!active);
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: _handleTap,
child: Container(
width: 200,
height: 200,
color: active ? Colors.green : Colors.grey,
child: Center(
child: Text(
active ? "Active" : "Inactive",
style: TextStyle(
fontSize: 50,
color: active ? Colors.white : Colors.black,
),
),
)
),
);
}
}
分析:
1、父 Widget 功能:
管理 _active 状态;
实现 _tapAction ,当方块被点击时调用方法;
当状态改变时,调用 setState 方法;
2、子 widget 功能:
检测到点击时,通知父 widget;
注意:它时继承自 StatelessWidget 。
2、Widget 管理自己的状态
import 'package:flutter/material.dart';
//自定义Son类, 继承自StatefulWidget
class CustomSonClass extends StatefulWidget {
const CustomSonClass({super.key});
@override
State<CustomSonClass> createState() => _CustomSonClassState();
}
class _CustomSonClassState extends State<CustomSonClass> {
//是否选中
bool _isSelect = false;
void _clickActionTap(){
setState(() {
_isSelect = !_isSelect;
});
}
@override
Widget build(BuildContext context) {
return GestureDetector(//手势事件
onTap: _clickActionTap,
child: Container(
width: 200.0,
height: 200.0,
decoration: BoxDecoration(
color: _isSelect ? Colors.grey : Colors.green,
),
child: Center(
child: Text(
_isSelect ? 'Inactive' : 'Active',
style: TextStyle(
fontSize: 30,
color: _isSelect ? Colors.black : Colors.white,
),
),
),
),
);
}
}
3、混合状态管理
父 widget 和 widget 两者都可以进行状态刷新。
import 'package:flutter/material.dart';
//superclass
class SuperClass extends StatefulWidget {
const SuperClass({super.key});
@override
State<SuperClass> createState() => _SuperClassState();
}
class _SuperClassState extends State<SuperClass> {
bool _active = false;//父组件是否激活
void _tapAction(bool value){//父组件状态改变的回调
setState(() {
_active = value;
});
}
@override
Widget build(BuildContext context) {
return SubClass(
active: _active,
onChanged: _tapAction,
);
}
}
//subclass
class SubClass extends StatefulWidget {
const SubClass({
super.key,
required this.active,
required this.onChanged,
});
final bool active;//子组件是否激活
final ValueChanged<bool> onChanged;//子组件状态改变的回调
@override
State<SubClass> createState() => _SubClassState();
}
class _SubClassState extends State<SubClass> {
bool _highlight = false;
void _handleTapDown(TapDownDetails details){
setState(() {
_highlight = true;
});
}
void _handleTapUp(TapUpDetails details){
setState(() {
_highlight = false;
});
}
void _handleTapCancel(){
setState(() {
_highlight = false;
});
}
void _handelTap(){
widget.onChanged(!widget.active);
}
@override
Widget build(BuildContext context) {
// 在按下时添加绿色边框,当抬起时,取消高亮
return GestureDetector(
onTapDown: _handleTapDown,
onTapUp: _handleTapUp,
onTapCancel: _handleTapCancel,
onTap: _handelTap,
child: Container(
width: 200,
height: 200,
decoration: BoxDecoration(
color: widget.active ? Colors.red : Colors.orange,
border: _highlight ? Border.all(color: Colors.green, width: 10) : null,
),
child: Center(
child: Text(
widget.active ? 'Active' : 'Inactive',
style: TextStyle(
fontSize: 40,
color: widget.active ? Colors.green : Colors.black,
),
),
),
),
);
}
}
4、全局状态管理
用来做 APP 级别的状态控制,如切换语言。其实现的方法如下:
1、全局通知:在需要改变状态的组件的 initState 方法中订阅该事件。当收到通知后调用 setState() 方法重新 build 一下自身即可。
2、使用专门用于状态管理的包,如 Provider、Redux 等。