flutter中状态管理介绍
问题背景
响应式的编程框架中都会有一个永恒的主题——“状态(State)管理”,无论是在 React/Vue(两者都是支持响应式编程的 Web 开发框架)还是 Flutter 中,他们讨论的问题和解决的思想都是一致的。我们想一个问题,StatefulWidget的状态应该被谁管理?答案是取决于实际情况!以下是管理状态的最常见的方法: Widget 管理自己的状态。 Widget 管理子 Widget 状态。 混合管理(父 Widget 和子 Widget 都管理状态)。 如何决定使用哪种管理方法? 如果状态是用户数据,如复选框的选中状态、滑块的位置,则该状态最好由父 Widget 管理。 如果状态是有关界面外观效果的,例如颜色、动画,那么状态最好由 Widget 本身来管理。 如果某一个状态是不同 Widget 共享的则最好由它们共同的父 Widget 管理。 在 Widget 内部管理状态封装性会好一些,而在父 Widget 中管理会比较灵活。有些时候,如果不确定到底该怎么管理状态,那么推荐的首选是在父 Widget 中管理(灵活会显得更重要一些)。
问题分析
(1)Widget管理自身状态 我们实现一个TapboxA,在它对应的_TapboxAState 类: 管理TapboxA的状态。 定义_active变量:确定盒子的当前颜色的布尔值。 定义_handleTap()函数,该函数在点击该盒子时更新_active的值,并调用setState()方法以更新UI。 (2)父Widget管理子Widget的状态 对于父Widget来说,管理状态并告诉其子Widget何时更新通常是比较好的方式。 在后面的示例中,TapboxB通过回调将其状态导出到其父组件,状态由父组件管理,因此它的父组件为StatefulWidget。但是由于TapboxB不管理任何状态,所以TapboxB为StatelessWidget。 ParentWidgetState 父类组件需要实现的功能: 为TapboxB 管理_active状态。 实现_handleTapboxChanged(),当盒子被点击时调用的方法。 当状态改变时,调用setState()更新UI。 TapboxB 子组件类的功能: 继承StatelessWidget类,因为所有状态都由其父组件处理。 当检测到点击时,它会通知父组件。
问题解决
上面对两种实现(1)Widget管理自身状态(2)父Widget管理子Widget的状态的实现方式进行了基本分析。下面直接上代码: (1)Widget管理自身状态,代码如下:
import 'package:flutter/material.dart';
class Test extends StatefulWidget {
_TestState createState() => _TestState();
}
class _TestState extends State<Test> {
bool _active = false;
void _handleTap() {
setState(() {
_active = !_active;
});
}
Widget build(BuildContext context) {
return GestureDetector(
// 点击回调_handleTap方法设置state并重新渲染
onTap: _handleTap,
child: Container(
child: Center(
child: Text(
_active ? 'Active' : 'Inactive',
style: TextStyle(fontSize: 32.0, color: Colors.white),
),
),
width: 200.0,
height: 200.0,
decoration: BoxDecoration(
color: _active ? Colors.lightGreen[700] : Colors.grey[600],
),
),
);
}
}
运行结果如下:
(2)父Widget管理子Widget的状态,代码如下:
import 'package:flutter/material.dart';
class Test extends StatefulWidget {
_TestState createState() => _TestState();
}
class _TestState extends State<Test> {
bool _active = false;
void _handleTapboxChanged(bool newValue) {
setState(() {
_active = newValue;
});
}
@override
Widget build(BuildContext context) {
return Container(
child: TapBoxB(
active: _active,
// 回调_handleTapboxChanged方法
onChanged: _handleTapboxChanged,
),
);
}
}
//------------------------- TapBoxB ----------------------------------
class TapBoxB extends StatelessWidget {
TapBoxB({Key? key, this.active = false, required this.onChanged})
: super(key: key);
final bool active;
final ValueChanged<bool> onChanged;
void _handleTap() {
// 回调onChanged方法,onChanged作为成员变量函数由构造方法传入
onChanged(!active);
}
Widget build(BuildContext context) {
return GestureDetector(
// 响应点击事件
onTap: _handleTap,
child: Container(
child: Center(
child: Text(
active ? 'Active' : 'Inactive',
style: TextStyle(fontSize: 32.0, color: Colors.white),
),
),
width: 200.0,
height: 200.0,
decoration: BoxDecoration(
color: active ? Colors.lightGreen[700] : Colors.grey[600],
),
),
);
}
}
运行结果如下:
问题总结
本文介绍了flutter中状态管理的基本实现方式,(1)Widget管理自身状态(2)父Widget管理子Widget的状态,有兴趣的同学可以进一步深入研究。