【Flutter】 Flutter 状态管理 BLoC 简明使用指南

2023-06-27 10:56:29

一、前言

🎉想要精通 Flutter,掌握更多技巧和最佳实践?好消息来了!👉 Flutter专栏->Flutter Developer 101 入门小册 正在等你!📚

🔍这里有你需要的所有 Flutter 学习资源,包括代码示例和深度解析。🎯

⏰专栏内容持续更新,价格也会随之上涨。现在加入,享受最优惠的价格!💰

🚀现在,让我们开始今天的 Flutter 之旅吧!🌍

在 Flutter 的世界里,状态管理是一个永恒的话题。

有许多不同的状态管理方案,而 BLoC(Business Logic Component)设计模式是其中的佼佼者。

BLoC 是由 Google 开发者 Advocate Paolo Soares 和 Cong Hui 提出的,它的主要目标是将业务逻辑从 UI 中分离出来,使得代码更加清晰,易于测试和复用。

那么,为什么我们要选择 Flutter BLoC 呢?

首先,BLoC 是基于流(Stream)的,这意味着我们可以利用 Dart 的强大的异步特性。

其次,BLoC 是完全独立于 UI 的,这使得我们可以在不同的 UI 组件之间共享和复用状态。

最后,BLoC 是由 Google 官方推荐的,这意味着它有着良好的社区支持和丰富的学习资源。

二、Flutter BLoC 的安装和配置

要开始使用 Flutter BLoC,我们首先需要在项目中安装它。打开你的 pubspec.yaml 文件,添加以下依赖:

dependencies:
  flutter_bloc: ^8.1.3

然后,运行 flutter packages get 命令来获取包。

三、Flutter BLoC 的基本使用

在 Flutter BLoC 中,我们主要会使用到三个组件:BLoC、BlocProvider 和 BlocBuilder。

首先,我们需要创建一个 BLoC。BLoC 是一个简单的 Dart 类,它接收输入(事件)并产生输出(状态)。以下是一个简单的 BLoC 的例子:

class CounterBloc extends Bloc<CounterEvent, int> {
  CounterBloc() : super(0);

  
  Stream<int> mapEventToState(CounterEvent event) async* {
    switch (event) {
      case CounterEvent.increment:
        yield state + 1;
        break;
      case CounterEvent.decrement:
        yield state - 1;
        break;
    }
  }
}

然后,我们需要使用 BlocProvider 来提供 BLoC。BlocProvider 是一个 Flutter widget,它将 BLoC 提供给它的子 widget。以下是如何使用 BlocProvider 的例子:

BlocProvider(
  create: (context) => CounterBloc(),
  child: CounterPage(),
)

最后,我们需要使用 BlocBuilder 来响应状态的变化。BlocBuilder 是一个 Flutter widget,它接收一个 BLoC 和一个 builder 函数,当 BLoC 的状态发生变化时,它会调用 builder 函数并重建 widget。以下是如何使用 BlocBuilder 的例子:

BlocBuilder<CounterBloc, int>(
  builder: (context, count) {
    return Text('$count');
  },
)

四、Flutter BLoC 的简单示例

让我们通过一个简单的计数器应用来看看如何在实践中使用 Flutter BLoC。

在这个应用中,我们将创建一个简单的计数器,它有两个按钮,一个用于增加计数,一个用于减少计数。

以下是完整的代码:

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

enum CounterEvent { increment, decrement }

class CounterBloc extends Bloc<CounterEvent, int> {
  CounterBloc() : super(0);

  
  Stream<int> mapEventToState(CounterEvent event) async* {
    switch (event) {
      case CounterEvent.increment:
        yield state + 1;
        break;
      case CounterEvent.decrement:
        yield state - 1;
        break;
    }
  }
}

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

class App extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      home: BlocProvider(
        create: (context) => CounterBloc(),
        child: CounterPage(),
      ),
    );
  }
}

class CounterPage extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Counter')),
      body: BlocBuilder<CounterBloc, int>(
        builder: (context, count) {
          return Center(
            child: Text(
              '$count',
              style: TextStyle(fontSize: 24.0),
            ),
          );
        },
      ),
      floatingActionButton: Column(
        crossAxisAlignment: CrossAxisAlignment.end,
        mainAxisAlignment: MainAxisAlignment.end,
        children: <Widget>[
          Padding(
            padding: EdgeInsets.symmetric(vertical: 5.0),
            child: FloatingActionButton(
              child: Icon(Icons.add),
              onPressed: () {
                BlocProvider.of<CounterBloc>(context).add(CounterEvent.increment);
              },
            ),
          ),
          Padding(
            padding: EdgeInsets.symmetric(vertical: 5.0),
            child: FloatingActionButton(
              child: Icon(Icons.remove),
              onPressed: () {
                BlocProvider.of<CounterBloc>(context).add(CounterEvent.decrement);
              },
            ),
          ),
        ],
      ),
    );
  }
}

在这个例子中,我们首先定义了一个 CounterEvent 枚举,它有两个值:incrementdecrement。然后,我们创建了一个 CounterBloc,它接收 CounterEvent 作为输入,并输出一个整数作为状态。在 mapEventToState 方法中,我们根据接收到的事件来更新状态。

CounterPage 中,我们使用 BlocBuilder 来构建 UI。当 CounterBloc 的状态发生变化时,BlocBuilder 会调用它的 builder 函数并重建 UI。在 floatingActionButton 中,我们添加了两个按钮,一个用于发送 increment 事件,一个用于发送 decrement 事件。

五、总结

通过这篇文章,我们对 Flutter BLoC 有了一个初步的了解。我们学习了如何安装和配置 Flutter BLoC,如何创建和使用 BLoC,以及如何通过一个简单的计数器应用来实践 Flutter BLoC。

Flutter BLoC 是一个强大的状态管理库,它可以帮助我们更好地组织和管理状态,使我们的代码更加清晰和可维护。然而,Flutter BLoC 也有它的

复杂性,特别是对于初学者来说,理解和使用 BLoC 可能会有一些困难。但是,一旦你理解了 BLoC 的核心概念,你就会发现它是一个非常强大和灵活的工具。

在接下来的文章中,我们将深入探讨 Flutter BLoC 的更多特性和用法,包括如何处理异步事件,如何测试 BLoC,以及如何使用 BLoC 来构建更复杂的应用。希望你会继续关注我们的系列文章,一起学习和探索 Flutter BLoC。

🚀对 Flutter 好奇?想深入探索?👉 Flutter专栏->Flutter Developer 101 入门小册 是你的最佳伙伴!📚

👀你将在这里找到全面的 Flutter 学习资源,包括代码示例和深度解析。🔍

💡想知道如何用 Flutter 构建应用?答案就在我们的专栏!🎯

⏰别等了,专栏内容持续更新,价格也会随之上涨。现在加入,享受最优惠的价格!💰

🌍一起在 Flutter 的世界中探索吧!想了解更多?点击这里:Flutter Developer 101 入门小册 专栏指引 🚩

更多推荐

基于 Vue 和 SpringBoot 的医院门诊预约挂号系统源代码+数据库

基于Vue和SpringBoot的医院门诊预约挂号系统完整代码下载地址:基于Vue和SpringBoot的医院门诊预约挂号系统源代码+数据库软件简介本软件是《基于Vue的医院门诊预约挂号管理系统》,主要包含数据中心、科室医生模块、预约挂号模块、医院时政这四大模块。预约挂号系统采用了基于角色的访问控制,角色和菜单关联,一

Flask-[实现websocket]-(2): flask-socketio文档学习

一、简单项目的构建flask_websocket|---static|---js|---jquery-3.7.0.min.js|---socket.io_4.3.1.js|---templates|---home|---group_chat.html|---index.html|---app.py1.1、python环

驱动开发-字符设备的内部实现

1、字符设备驱动内部的注册过程对register_chrdev内部的实现过程分析,注册字符驱动的过程有以下几步1、分配structcdev对象空间2、初始化structcdev对象3、注册cdev对象以上三步完成了字符设备驱动的注册2、structcdev结构体分析只要有一个驱动存在于系统内核中,就会存在一个struc

[ESP32 IDF+Vscode]蓝牙配网后采用上传温湿度数据至阿里云(MQTT协议)

阿里云平台的设置参考文章:http://t.csdn.cn/RzLGqhttp://t.csdn.cn/RzLGqBlufi配网1.简介BluFi是一款基于蓝牙通道的Wi-Fi网络配置功能,适用于ESP32。它通过安全协议将Wi-Fi配置和证书传输到ESP32,然后ESP32可基于这些信息连接到AP或建立SoftAP。

Node.js 20.6支持.env配置文件,加入C++垃圾回收函式库Oilpan

在最新版本20.6.0中,Node.js现在内置了对.env文件的支持。现在,您可以将环境变量从.env文件加载到process.envNode.js应用程序中,完全无依赖。加载.env文件现在非常简单:node--env-file.env什么是.env?.env文件用于配置将存在于正在运行的应用程序中的环境变量。这个

浅谈STL|STL函数对象篇

一.函数对象概念概念:·重载函数调用操作符的类,其对象常称为函数对象·函数对象使用重载的()时,行为类似函数调用,也叫仿函数本质:函数对象(仿函数)是一个类,不是一个函数特点函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值;函数对象超出普通函数的概念,函数对象可以有自己的状态;函数对象可以作为参数传递

SD系列——图像高清化算法方法

图像高清化算法方法文章目录图像高清化算法方法一、通过Extras选项卡执行放大算法二、通过SDupscale脚本增强细节三、txt2img页面下的HiresFix四、扩展插件UltimateSDupscale+ControlNetTile参数调整单用UltimateSDUpscale小结五、TiledDiffusion

基于springboot大学生租房系统springboot10

大家好✌!我是CZ淡陌。一名专注以理论为基础实战为主的技术博主,将再这里为大家分享优质的实战项目,本人在Java毕业设计领域有多年的经验,陆续会更新更多优质的Java实战项目,希望你能有所收获,少走一些弯路,向着优秀程序员前行!🍅更多优质项目👇🏻👇🏻可点击下方获取🍅文章底部或评论区获取🍅Java项目精品实

数据结构——堆

堆文章目录堆1.什么是堆2.堆的两个特性3.父子节点下标之间的关系4.堆的实现4.1堆的插入HeapPush4.1.1向上调整算法AdjustUp:4.1.2AdjustUp代码实现(以大堆为例)4.1.3HeapPush实现4.1.4时间复杂度4.2堆的删除HeapPop4.2.1向下调整算法AdjustDown4.

基于Docker的JMeter分布式压测实战讲解

一个JMeter实例可能无法产生足够的负载来对你的应用程序进行压力测试。如本网站所示,一个JMeter实例将能够控制许多其他的远程JMeter实例,并对你的应用程序产生更大的负载。JMeter使用JavaRMI[远程方法调用]来与分布式网络中的对象进行交互。JMeter主站和从站的通信如下图所示:我们需要为每个Slav

Hive内置函数字典

写在前面:HQL同SQL有很多的类似语法,同学熟悉SQL后一般学习起来非常轻松,写一篇文章列举常用函数,方便查找和学习。1.执行模式1.1BatchMode批处理模式当使用-e或-f选项运行$HIVE_HOME/bin/hive时,它将以批处理模式执行SQL命令。所谓的批处理可以理解为一次性执行,执行完毕退出#-e$H

热文推荐