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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,875评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,569评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,475评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,459评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,537评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,563评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,580评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,326评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,773评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,086评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,252评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,921评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,566评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,190评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,435评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,129评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,125评论 2 352

推荐阅读更多精彩内容