以下内容参考《Flutter中文开发者社区》和《Flutter实战·第二版》,仅为个人学习、熟悉Flutter,不同版本可能有稍微不一样。
环境
///
/// 例子来源:
/// Widgets 介绍:https://flutter.cn/docs/development/ui/widgets-intro
/// 《Flutter实战·第二版》:https://book.flutterchina.club/chapter2/state_manage.html
///
/// 环境:
/// Flutter 3.10.1 • channel stable • https://github.com/flutter/flutter.git
/// Framework • revision d3d8effc68 (7 days ago) • 2023-05-16 17:59:05 -0700
/// Engine • revision b4fb11214d
/// Tools • Dart 3.0.1 • DevTools 2.23.1
///
管理状态的最常见的方法:
- Widget 管理自己的状态。
- Widget 管理子 Widget 状态。
- 混合管理(父 Widget 和子 Widget 都管理状态)。
如何决定使用哪种管理方法?下面是官方给出的一些原则可以帮助你做决定:
- 如果状态是用户数据,如复选框的选中状态、滑块的位置,则该状态最好由父 Widget 管理。
- 如果状态是有关界面外观效果的,例如颜色、动画,那么状态最好由 Widget 本身来管理。
- 如果某一个状态是不同 Widget 共享的则最好由它们共同的父 Widget 管理。
Widget 管理自己的状态
/// TapBoxA 管理自身状态.
class TapBoxA extends StatefulWidget {
const TapBoxA({super.key});
@override
State<TapBoxA> createState() => _TapBoxAState();
}
class _TapBoxAState extends State<TapBoxA> {
bool _active = false;
void _handleTap() {
setState(() {
_active = !_active;
});
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: _handleTap,
child: Center(
child: Container(
width: 200.0,
height: 200.0,
decoration: BoxDecoration(
color: _active ? Colors.lightGreen[700] : Colors.grey[600],
),
child: Center(
child: Text(
_active ? "Active" : "Inactive",
style: const TextStyle(fontSize: 30, color: Colors.white),
),
),
),
),
);
}
}
Widget 管理子 Widget 状态。
/// ParentWidget 为 TapBoxB 管理状态.
/// ------------------------ ParentWidget --------------------------------
class ParentWidget extends StatefulWidget {
const ParentWidget({super.key});
@override
State<ParentWidget> createState() => ParentWidgetState();
}
class ParentWidgetState extends State<ParentWidget> {
bool _active = false;
void handleTapBoxChange(bool newValue) {
setState(() {
_active = newValue;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("父管理子Widget的状态"),
backgroundColor: Colors.black,
),
body: TapBoxB(
active: _active,
onChanged: handleTapBoxChange,
),
);
}
}
///------------------------ TapBoxB ----------------------------------
class TapBoxB extends StatelessWidget {
const TapBoxB({super.key, this.active = false, required this.onChanged});
final bool active;
final ValueChanged<bool> onChanged;
void _handleTap() {
onChanged(!active);
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: _handleTap,
child: Center(
child: Container(
width: 200.0,
height: 200.0,
decoration: BoxDecoration(
color: active ? Colors.red[700] : Colors.blue[600],
),
child: Center(
child: Text(
active ? "Active" : "Inactive",
style: const TextStyle(fontSize: 30, color: Colors.white),
),
),
),
),
);
}
}
混合状态管理
/// ------------------------ ParentWidgetC --------------------------------
class ParentWidgetC extends StatefulWidget {
const ParentWidgetC({super.key});
@override
State<ParentWidgetC> createState() => _ParentWidgetCState();
}
class _ParentWidgetCState extends State<ParentWidgetC> {
bool _activeState = false;
void _handleTabBoxChange(bool newValue) {
setState(() {
_activeState = newValue;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("混合状态管理", style: TextStyle(color: Colors.white)),
backgroundColor: Colors.blue[500],
),
body: TapBoxC(
active: _activeState,
onChanged: _handleTabBoxChange,
),
);
}
}
///----------------------------- TapBoxC ------------------------------
class TapBoxC extends StatefulWidget {
const TapBoxC({super.key, this.active = false, required this.onChanged});
final bool active;
final ValueChanged<bool> onChanged;
@override
State<TapBoxC> createState() => _TapBoxCState();
}
class _TapBoxCState extends State<TapBoxC> {
bool highlight = false;
void handleTapDown(TapDownDetails details) {
setState(() {
highlight = true;
});
}
void handleTapUp(TapUpDetails details) {
setState(() {
highlight = false;
});
}
void handleTapCancel() {
setState(() {
highlight = false;
});
}
void handleTap() {
setState(() {
widget.onChanged(!widget.active);
});
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: handleTap,
onTapDown: handleTapDown,
onTapUp: handleTapUp,
onTapCancel: handleTapCancel,
child: Center(
child: Container(
width: 200.0,
height: 200.0,
decoration: BoxDecoration(
color: widget.active ? Colors.pink[200] : Colors.cyan[500],
border: highlight
? Border.all(color: Colors.orange[700]!, width: 10,)
//Border(top: BorderSide(color: Colors.orange[700]!, width: 10))
: null,
),
child: Center(
child: Text(
widget.active ? "Active" : "Inactive",
style: const TextStyle(fontSize: 30, color: Colors.white),
),
),
),
),
);
}
}