美文网首页
Flutter StatefullWidget 三种状态管理De

Flutter StatefullWidget 三种状态管理De

作者: 程就人生 | 来源:发表于2021-07-10 11:19 被阅读0次

    在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()
              ],
            )
        );
      }
    }
    

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


    效果图

    相关文章

      网友评论

          本文标题:Flutter StatefullWidget 三种状态管理De

          本文链接:https://www.haomeiwen.com/subject/rgkqpltx.html