Flutter StatefullWidget 三种状态管理Demo

在Flutter中,组件的状态管理还是非常重要的,组件要么是无状态的组件,要么是有状态的组件。无状态的组件使用起来似乎并不复杂,有状态的组件又是怎么管理的呢?这里就谈一谈 StatefullWidget 与 State 对组件状态的管理。状态管理又可以分为三类:自己管理,父组件管理,父子组件混合管理。

第一种自己的状态自己管理,是最简单的一种,看代码;

import 'package:flutter/material.dart';
//自己的状态自己管理,继承StatefulWidget
class SelfManageStatus extends StatefulWidget{

  @override
  State<StatefulWidget> createState() {
    return _SelfManageStatusState();
  }
}
//状态类,一个StatefulWidget 对应一个 State
class _SelfManageStatusState extends State<SelfManageStatus>{
  //点击次数,默认 0
  int clickNum = 0;
  //点击事件
  void doClick(){
    // 状态由调用setState()管理
    setState(() {
      // 每次点击加 1
      clickNum++;
    });
  }

  /// 构建控件元素
  @override
  Widget build(BuildContext context) {
    // 使用GestureDetector监测手势相关事件
    return GestureDetector(
      onTap: doClick,
      child: Container(
          child: Center(
              child: Column(
                children: <Widget>[
                    Text(
                      "自己管理,点我呀",
                      style: TextStyle(fontSize: 18,color: Colors.yellow),
                    ),
                    Text("点击次数:$clickNum"),
                  ],
              )
        ),
        //宽度,double.infinity:百分之百
        width: double.infinity,
        height: 100,
        color: Colors.red
      ),
    );
  }
}

说明:通过这个demo可以看出,StatefulWidget 与 State 的使用是一一对应的,状态管理交由 State 处理;手势在手机屏幕上滑动通过 GestureDetector类检测,状态的管理通过 State 类的 setState() 方法控制。把 setState() 这个方法去掉,就做不到状态的保持。

第二种情况,父组件管理;

//父管理子状态,父组件继承StatefulWidget
class ParentManageStatus extends StatefulWidget{
  @override
  State<StatefulWidget> createState() {
    return _ParentManageStatusState();
  }
}
//父组件状态
class _ParentManageStatusState extends State<ParentManageStatus>{
  //点击次数,默认0
  int clickNum = 0;
  //当数量发生改变时,由父组件调用setState()管理状态
  void handleClick(int num){
    setState(() {
      //每点击一次加num,该num由子组件传递过来
      clickNum+=num;
    });
  }
  @override
  Widget build(BuildContext context) {
    return Container(
      child: ChildArea(
        clickNum : clickNum,
        numChanged : handleClick,
      ),
    );
  }
}
//子组件继承StatelessWidget无状态组件
class ChildArea extends StatelessWidget{
  //不可改变的点击数量
  final clickNum;
  //状态的传递
  final ValueChanged<int> numChanged;  
  ChildArea({this.clickNum, required this.numChanged});
  //点击事件
  void doClick(){
    /// 没有去管理状态,交由父类管理
    numChanged(1);
  }
  @override
  Widget build(BuildContext context) {
    // 使用GestureDetector监测手势相关事件
    return GestureDetector(
      // 点击事件监听
      onTap: doClick,
      child: Container(
        child: Center(
            child: Column(
              children: <Widget>[
                Text(
                  "子组件父管理,点我呀",
                  style: TextStyle(fontSize: 18,color: Colors.yellow),
                ),
                Text("点击次数:$clickNum"),
              ],
            )
        ),
        width: double.infinity,
        height: 100,
        color: Colors.green
      ),
    );
  }
}

说明:子组件继承 StatelessWidget 无状态组件,对组件的状态无需管理,监听到点击事件时,将状态交由父组件管理,父组件管理后再传递过来回显。父组件管理就是一个有状态的组件和无状态的组件的结合。

第三种情况,状态混合管理;

import 'package:flutter/material.dart';

//父子状态混合管理,父组件
class HybridManageStatus extends StatefulWidget{
  @override
  State<StatefulWidget> createState() {
    return _HybridManageStatusState();
  }

}
//父组件状态
class _HybridManageStatusState extends State<HybridManageStatus>{
  // 子点击次数
  int clickNum = 0;
  // 父点击次数
  int pclickNum = 0;
  //点击事件,调用setState()进行状态保持
  void handleClick(int num){
    setState(() {
      clickNum = num;
      pclickNum++;
    });
  }
  //点击事件,调用setState()进行状态保持
  void doClick(){
    setState(() {
      pclickNum++;
    });
  }
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
        onTap: doClick,
        child: Container(
              child: Center(
                child: Column(
                children: <Widget>[
                ChildStatus(
                clickNum: this.clickNum,
                  numChanged: handleClick,
                ),
                Text(
                  "混合管理,我是父组件里的控件",
                  style: TextStyle(fontSize: 18,color: Colors.yellow),
                ),
                Text("子点击次数:$clickNum,父点击次数:$pclickNum"),
                ],
              ),
            ),
            width: double.infinity,
            height: 200,
            color: Colors.grey
         ),
    );
  }

}
//子组件
class ChildStatus extends StatefulWidget{

  final clickNum;

  final ValueChanged<int> numChanged;

  ChildStatus({this.clickNum, required this.numChanged});

  @override
  State<StatefulWidget> createState() {
    return _ChildStatusState();
  }
}
//子组件状态
class _ChildStatusState extends State<ChildStatus>{
  int clickNum = 0;
  void doClick(){
    setState((){
      clickNum++;
    });
    widget.numChanged(clickNum);
  }
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: doClick,
      child: Container(
        child: Center(
            child: Column(
              children: <Widget>[
                Text(
                  "混合管理,我是父组件里的子组件控件,点我呀",
                  style: TextStyle(fontSize: 18,color: Colors.yellow),
                ),
                Text("点击次数:$clickNum"),
              ],
            )
        ),
        width: double.infinity,
        height: 100,
        color: Colors.blue,
      ),
    );
  }
}

说明:

  1. 混合管理,父组件是有状态的组件,子组件也是有状态的组件,是两个有状态组件的结合,子组件状态的变更会通知父组件(最重要的一点)。混合管理对于新手来说,还是有点复杂的,但也是使用频率最多的状态管理,所以必须熟练掌握。
    2.这个demo里,在父组件里又单独加了一个组件,作为参照,父组件包含子组件,但是父组件的控件在子组件范围外,子组件以外的父组件只受父组件的影响,和子组件无关。

代码写完了,将这三种状态整合起来

import 'package:flutter/material.dart';

import 'OneArea.dart';
import 'ThreeAreaParent.dart';
import 'TwoAreaParent.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text("welocom to flutter"),
        ),
        body: Center(
          child: ThreeState(),
        ),
      ),
    );
  }
}
//继承无状态组件,整合三种状态的组件
class ThreeState extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    return Container(
        child: Column(
          children: <Widget>[
            OneArea(),
            TwoAreaParent(),
            ThreeAreaParent()
          ],
        )
    );
  }
}

运行代码,每一块各点击三下,确认统计数字是否正确;


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章