Flutter 状态管理

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 等。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容