LOADING

加载过慢请开启缓存,浏览器默认开启

flutter状态管理初探

2023/2/10
flutter 入门

纵观响应式框架开发,状态管理是一个绕不开的话题。不论是 React/Vue,还是 flutter 中,其核心思想基本一致。在 flutter 中,有以下三种基本思想:

  1. 组件自身管理状态(封装性高)
  2. 父级组件管理状态(灵活性高)
  3. 混合管理状态
flutter 状态管理指南:
  1. 用户数据交由父级管理
  2. widget 样式外观数据自身管理
  3. 如不确定该使用何种管理方式,建议使用父级管理,可以拥有极高的灵活性
demo 示例
  1. 自身管理
class TapBoxA extends StatefulWidget {
  const TapBoxA({super.key});
  @override
  State<TapBoxA> createState() => _TapBoxAState();
}

class _TapBoxAState extends State<TapBoxA> {

  bool _active = false;

//点击事件触发setState修改状态,进而重新渲染
  void toggleActive(){
    setState(() {
      _active = !_active;
    });
  }

  @override
  Widget build(BuildContext context) {
    //手势事件
    return GestureDetector(
      onTap: toggleActive,
      child: Container(
        width: 100,
        height: 100,
        decoration: BoxDecoration(
          color: _active?Colors.lightGreen[400]:Colors.grey[400]
        ),
        child: Center(
          child: Text(_active?"active":"inActive"),
        ),
      ),
    );
  }
}
  1. 父级管理
class ParentWidget extends StatefulWidget {
  const ParentWidget({super.key});
  @override
  State<ParentWidget> createState() => _ParentWidgetState();
}

class _ParentWidgetState extends State<ParentWidget> {
  bool _active = false;
  void toggleActive(bool newVal){
    setState(() {
      _active = newVal;
    });
  }
  @override
  Widget build(BuildContext context) {
    return TapBoxB(active: _active, onChanged: toggleActive);
  }
}

class TapBoxB extends StatelessWidget {
  const TapBoxB({super.key, required this.active, required this.onChanged});4
  //该active类似于Vue中computed 相应父级 active,
  //为何使用final?
  /**
   *1. 因为当tap事件触发,则父级会重新渲染UI,意味着每次都是新的tapBoxB
   *2. 子组件内不存在任何修改该状态事件,所以使用final,onChange同理
   */
  final bool active;
  final ValueChanged<bool> onChanged;
  //onTap事件调用父级 toggleActive 事件
  void _handleTap(){
    onChanged(!active);
  }
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: _handleTap,
      child: Container(
        width: 100,
        height: 100,
        decoration: BoxDecoration(
          color: active?Colors.lightGreen[400]:Colors.grey[400]
        ),
        child: Center(
          child: Text(active?"active":"inActive"),
        ),
      ),
    );
  }
}
  1. 混合管理
class ParentWidgetC extends StatefulWidget {
  const ParentWidgetC({super.key});
  @override
  State<ParentWidgetC> createState() => _ParentWidgetCState();
}

class _ParentWidgetCState extends State<ParentWidgetC> {
  //父级负责active状态
  bool _active = false;
  void toggleActive(bool newVal) {
    setState(() {
      _active = newVal;
    });
  }
  @override
  Widget build(BuildContext context) {
    return TapBoxC(active: _active, onChanged: toggleActive);
  }
}

class TapBoxC extends StatefulWidget {
  const TapBoxC({super.key, required this.active, required this.onChanged});
  final bool active;
  final ValueChanged<bool> onChanged;
  @override
  State<TapBoxC> createState() => _TapBoxCState();
}

class _TapBoxCState extends State<TapBoxC> {
  //子组件自己维护高亮状态
  bool highLight = false;

  void _handleTap() {
    //在状态类中,可以使用widget获取上级
    widget.onChanged(!widget.active);
  }

  void _handleTapDown(TapDownDetails detail) {
    setState(() {
      highLight = true;
    });
  }

  void _handleTapUp(TapUpDetails detail) {
    setState(() {
      highLight = false;
    });
  }

  void _handleTapCancel() {
    setState(() {
      highLight = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: _handleTap,
      onTapDown: _handleTapDown,
      onTapUp: _handleTapUp,
      onTapCancel: _handleTapCancel,
      child: Container(
        width: 100,
        height: 100,
        decoration: BoxDecoration(
            color: widget.active ? Colors.lightGreen[400] : Colors.grey[400],
            border: highLight
                ? Border.all(color: Colors.lightBlue[300]!, width: 2)
                : null),
        child: Center(
          child: Text(widget.active ? "active" : "inActive"),
        ),
      ),
    );
  }
}