我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Flutter组件状态管理的3种方法

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Flutter组件状态管理的3种方法

前言

前面讲了Flutter布局,布局只是静态的。在Flutter中,组件分为StatelesslWidget和StatefulWidget。

  • StatelesslWidget

没有状态,是一成不变的。比如图标,文字,按钮等

  • StatefulWidget

有状态的组件,页面数据是动态的,或者会随着用户操作变化,比如多选框,文本输入框等。

有状态组件

重点来了,如何使用实现一个有状态的组件呢?

  • 有状态的组件一般由两个类构成,一个StatefulWidget子类和一个State子类.
  • State类包含了组件的build()方法,并且负责维护组件状态
  • 当这个组件的状态变化了,可以调用setState()方法来刷新页面

状态管理

由谁来负责状态管理呢?是组件本身,还是他的父类,两者都有又或是其他对象?答案是都可以。也就是说有三种方法实现状态管理:

1.组件自己管理自己的状态
2.组件的父组件管理状态
3.混搭管理

那么如何决定该用那种方式来进行状态管理呢?一般来讲有以下原则:

1.如果是用户数据,比如多选框是否被选中,一般是由选择第2种方法
2.如果动效,比如放大缩小,那一般用第1种方法

PS:如果你实在迷芒,就直接选择用第2种方法,用父类管理状态。

举例

组件自己管理自己的状态

如下代码:_TapboxAState这个State子类为TapboxA维护状态,内部定义了一个_active变量来决定当前是否为激活的状态,内部还定义了一个_handleTap()回调函数,来处理用户点击后的逻辑,并且调用了setState()生命周期方法,重新刷新页面。

import 'package:flutter/material.dart';

// TapboxA 自己管理状态
void main() => runApp(const MyApp());
//------------------------- TapboxA ----------------------------------

class TapboxA extends StatefulWidget {
  const TapboxA({Key? key}) : super(key: key);
  @override
  _TapboxAState createState() => _TapboxAState();
}

class _TapboxAState extends State<TapboxA> {
  bool _active = false;

  void _handleTap() {
    setState(() {
      _active = !_active;
    });
  }
  
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: _handleTap,
      child: Container(
        child: Center(
          child: Text(
            _active ? 'Active' : 'Inactive',
            style: const TextStyle(fontSize: 32.0, color: Colors.white),
          ),
        ),
        width: 200.0,
        height: 200.0,
        decoration: BoxDecoration(
          color: _active ? Colors.lightGreen[700] : Colors.grey[600],
        ),
      ),
    );
  }
}

//------------------------- MyApp ----------------------------------

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Flutter Demo'),
        ),
        body: const Center(
          child: TapboxA(),
        ),
      ),
    );
  }
}

父组件管理状态

更多时候我们需要父组件来决定子组件什么时候来更新状态,子组件只需要根据父组件传过来的参数进行合理的展示即可。这种情况下子组件并不需要维护状态,所以子组件是一个StatelessWidget,父组件ParentWidget才是StatefulWidget。代码如下:
父组件维护了一个_active变量用来标记是否为激活状态,并且实现了回调函数_handleTapboxChanged用来反转激活状态,供子组件调用。子组件TapboxB是一个无状态组件,只需要在被点击的时候通知父组件来管理状态。

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());


class ParentWidget extends StatefulWidget {
  const ParentWidget({Key? key}) : super(key: key);

  @override
  _ParentWidgetState createState() => _ParentWidgetState();
}

class _ParentWidgetState extends State<ParentWidget> {
  bool _active = false;

  void _handleTapboxChanged(bool newValue) {
    setState(() {
      _active = newValue;
    });
  }

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      child: TapboxB(
        active: _active,
        onChanged: _handleTapboxChanged,
      ),
    );
  }
}

//------------------------- TapboxB ----------------------------------

class TapboxB extends StatelessWidget {
  const TapboxB({
    Key? key,
    this.active = false,
    required this.onChanged,
  }) : super(key: key);

  final bool active;
  final ValueChanged<bool> onChanged;

  void _handleTap() {
    onChanged(!active);
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: _handleTap,
      child: Container(
        child: Center(
          child: Text(
            active ? 'Active' : 'Inactive',
            style: const TextStyle(fontSize: 32.0, color: Colors.white),
          ),
        ),
        width: 200.0,
        height: 200.0,
        decoration: BoxDecoration(
          color: active ? Colors.lightGreen[700] : Colors.grey[600],
        ),
      ),
    );
  }
}

//------------------------- MyApp ----------------------------------

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Flutter Demo'),
        ),
        body: const Center(
//          child: TapboxA(),
          child: ParentWidget(),

        ),
      ),
    );
  }
}

混搭管理

混搭管理状态,就是因为有些情况下我们需要父组件管理一部分状态,子组件独立管理另一部分状态。在本次,我们根据上例添加一个动效,按钮按下时要显示高亮状态(前文讲过,动效一类的状态一般要组件本身管理),抬起时取消高亮。
如下代码:ParentWidget负责维护_active状态来标志是否被激活,子组件TapboxC负责维护_highlight状态用来控制是否高亮显示。

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());


class ParentWidget extends StatefulWidget {
  const ParentWidget({Key? key}) : super(key: key);

  @override
  _ParentWidgetState createState() => _ParentWidgetState();
}

class _ParentWidgetState extends State<ParentWidget> {
  bool _active = false;

  void _handleTapboxChanged(bool newValue) {
    setState(() {
      _active = newValue;
    });
  }

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      child: TapboxC(
        active: _active,
        onChanged: _handleTapboxChanged,
      ),
    );
  }
}

//----------------------------- TapboxC ------------------------------

class TapboxC extends StatefulWidget {
  const TapboxC({
    Key? key,
    this.active = false,
    required this.onChanged,
  }) : super(key: key);

  final bool active;
  final ValueChanged<bool> onChanged;

  @override
  _TapboxCState createState() => _TapboxCState();
}

class _TapboxCState extends State<TapboxC> {
  bool _highlight = false;

  void _handleTapDown(TapDownDetails details) {
    setState(() {
      _highlight = true;
    });
  }

  void _handleTapUp(TapUpDetails details) {
    setState(() {
      _highlight = false;
    });
  }

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

  void _handleTap() {
    widget.onChanged(!widget.active);
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTapDown: _handleTapDown, // Handle the tap events in the order that
      onTapUp: _handleTapUp, // they occur: down, up, tap, cancel
      onTap: _handleTap,
      onTapCancel: _handleTapCancel,
      child: Container(
        child: Center(
          child: Text(widget.active ? 'Active' : 'Inactive',
              style: const TextStyle(fontSize: 32.0, color: Colors.white)),
        ),
        width: 200.0,
        height: 200.0,
        decoration: BoxDecoration(
          color: _highlight?Colors.lightGreen :widget.active ? Colors.lightGreen[700] : Colors.grey[600],
        ),
      ),
    );
  }
}
//------------------------- MyApp ----------------------------------

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Flutter Demo'),
        ),
        body: const Center(
//          child: TapboxA(),
          child: ParentWidget(),

        ),
      ),
    );
  }
}

当然你也可以把高亮显示的状态交给父组件来管理,但是当你开发完这个组件交给同事来用的时候,别人可能只会关注业务逻辑上的处理,不会关注的动效处理。

其他交互组件

Flutter内部预置了很多交互组件,甚至还有IOS风格的组件,都可以拿来用。如果有必要的话,可以向上面的例子一样自定义组件使用。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Flutter组件状态管理的3种方法

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Flutter组件状态管理的方法有哪些

这篇文章主要为大家展示了“Flutter组件状态管理的方法有哪些”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Flutter组件状态管理的方法有哪些”这篇文章吧。前言前面讲了Flutter布局,
2023-06-29

Vuex状态管理的方法是什么

这篇文章主要介绍“Vuex状态管理的方法是什么”,在日常操作中,相信很多人在Vuex状态管理的方法是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Vuex状态管理的方法是什么”的疑惑有所帮助!接下来,请跟
2023-06-03

vuex状态管理数据状态查询与更改的方法

本篇内容介绍了“vuex状态管理数据状态查询与更改的方法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!状态管理数据状态查询与更改1.main
2023-06-30

React各种状态管理器的原理及使用方法是什么

今天就跟大家聊聊有关React各种状态管理器的原理及使用方法是什么,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。首先我们要先知道什么是状态管理器,这玩意是干啥的?当我们在多个页面中使
2023-06-25

3种Android隐藏顶部状态栏及标题栏的方法

本文包含3种隐藏顶部状态栏及标题栏和一种隐藏Android 4.0平板底部状态栏的方法,分享给大家供大家参考,具体内容如下 方法一public class MainActivity extends Activity {@Overridepr
2022-06-06

Electron电源状态管理的方法是什么

这篇“Electron电源状态管理的方法是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Electron电源状态管理的方
2023-07-05

React中使用事件驱动进行状态管理的方法

这篇文章给大家分享的是有关React中使用事件驱动进行状态管理的方法的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。自 Hook 被引入 React 以来,Context API 与 Hook 库在应用状态管理中
2023-06-14

Vue之Pinia状态管理的方法是什么

这篇文章主要介绍“Vue之Pinia状态管理的方法是什么”,在日常操作中,相信很多人在Vue之Pinia状态管理的方法是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Vue之Pinia状态管理的方法是什么
2023-07-05

ReactNative状态管理redux使用的方法是什么

这篇“ReactNative状态管理redux使用的方法是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“ReactNat
2023-07-05

浅析集中式状态管理Vuex的使用方法

如何使用集中式状态管理的Vuex?下面本篇文章就带大家了解一下vuex,简单聊聊vuex的使用方法,希望对大家有所帮助!
2023-05-14

Vuex管理dialog、toast等常见全局性组件状态时唯一性的问题解决

工作中经常会用到类似于 dialog、toast、popover 等一些状态提示组件,这篇文章主要介绍了Vuex管理dialog、toast等常见全局性组件状态时唯一性的问题,需要的朋友可以参考下
2022-11-16

vista/win7本地连接状态未知,依赖服务或组无法启动的六种解决方法

症状:VISTA/WIN7突然无法上网,网络和共享中心显示未知,依赖服务javascript或组无法启动。诊断和修复显示无法运行,因为"诊断策略服务"没有运行。打开服务控制器,很多服务都启动不了(没有禁用),是Network Locatio
2023-05-25

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录