【Flutter】状态管理:高级状态管理 (Riverpod, BLoC)

news2024/10/26 2:26:32

当项目变得更加复杂时,简单的状态管理方式(如 setState()Provider)可能不足以有效地处理应用中状态的变化和业务逻辑的管理。在这种情况下,高级状态管理框架,如 RiverpodBLoC,可以提供更强大的工具,用于处理复杂的状态流、逻辑分离以及响应式编程。

在本教程中,我们将深入学习 RiverpodBLoC 这两种高级状态管理框架,理解它们的核心概念,学会如何将业务逻辑与 UI 分离,并使用 Stream 处理复杂的状态流。

Riverpod 状态管理框架

Riverpod 是由 Provider 的作者开发的一个更加灵活、强大且类型安全的状态管理框架。相比 ProviderRiverpod 提供了更清晰的状态管理方式,同时避免了一些常见的错误和限制。它支持全局和局部的状态管理,适用于大型应用的开发。

安装 Riverpod

首先,在 pubspec.yaml 文件中添加 riverpod 依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_riverpod: ^2.0.0

然后运行 flutter pub get 安装依赖。

Riverpod 核心概念

在使用 Riverpod 之前,需要了解它的几个核心概念:

  • Provider:是 Riverpod 的基本状态提供者。它可以创建、管理并共享状态。
  • ConsumerWidget:用于监听 Provider 并响应其状态变化。
  • StateProvider:提供一种简单的方式来管理和监听状态。
  • StateNotifierStateNotifierProvider:用于管理复杂的业务逻辑和状态。
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

// 定义一个 StateProvider 来管理状态
final counterProvider = StateProvider<int>((ref) => 0);

void main() {
  runApp(
    ProviderScope(
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return MaterialApp(
      home: CounterPage(),
    );
  }
}

class CounterPage extends ConsumerWidget {
  
  Widget build(BuildContext context, WidgetRef ref) {
    // 通过 ref 读取 counterProvider 的状态
    final counter = ref.watch(counterProvider);

    return Scaffold(
      appBar: AppBar(
        title: Text('Riverpod Counter Example'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('You have pushed the button this many times:'),
            Text(
              '$counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          // 更新状态
          ref.read(counterProvider.notifier).state++;
        },
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

代码详解

  1. StateProvidercounterProvider 是一个 StateProvider,它用于管理整型计数器状态。我们定义了一个初始值 0,并通过 ref.watch 监听状态的变化。

  2. ProviderScope:这是 Riverpod 的核心组件,用于提供上下文中可访问的状态。ProviderScope 必须在应用的最顶层。

  3. ConsumerWidgetCounterPage 继承自 ConsumerWidget,用于监听状态提供者 counterProvider,并在状态变化时重新构建 UI。

  4. 状态更新ref.read(counterProvider.notifier).state++ 用于更新状态。这里我们通过 read 方法获取 StateProvidernotifier,然后修改其状态。

BLoC 状态管理框架

BLoC(Business Logic Component)是一种基于响应式编程的状态管理模式,它通过 Stream 处理复杂的状态流,实现了业务逻辑和 UI 的完全分离。这种模式适用于大型项目,能够确保代码的可维护性和扩展性。

BLoC 的核心思想是将事件流(Event)转换为状态流(State),从而使得业务逻辑独立于界面逻辑。

安装 flutter_bloc

pubspec.yaml 文件中添加 flutter_bloc 包依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_bloc: ^8.0.0
  bloc: ^8.0.0

运行 flutter pub get 安装依赖。

BLoC 核心概念

  • BLoC:用于处理输入的事件并输出相应的状态。它封装了业务逻辑和状态转换。
  • CubitCubitBLoC 的简化版本,通常用于处理简单的状态变化。
  • StreamBLoCCubit 都依赖 Stream 来传递状态更新。
  • BlocProviderBlocBuilder:用于提供 BLoC 实例并在 UI 中监听状态变化。

示例:使用 Cubit 实现计数器

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

// 定义 Cubit,用于管理计数器状态
class CounterCubit extends Cubit<int> {
  CounterCubit() : super(0);

  void increment() => emit(state + 1);  // 更新状态
}

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

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

class CounterPage extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('BLoC Counter Example'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('You have pushed the button this many times:'),
            BlocBuilder<CounterCubit, int>(
              builder: (context, count) {
                return Text(
                  '$count',
                  style: Theme.of(context).textTheme.headline4,
                );
              },
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          // 获取 CounterCubit 实例并调用 increment
          context.read<CounterCubit>().increment();
        },
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

代码详解

  1. CounterCubitCubitBLoC 的简化版本,用于处理简单的状态更新。这里我们定义了一个计数器 Cubit,初始状态为 0,并通过 increment() 方法更新状态。

  2. BlocProvider:提供 CounterCubit 实例,并使其在子组件中可访问。

  3. BlocBuilder:用于监听 Cubit 的状态变化,并根据新的状态更新 UI。

  4. 状态更新:通过 context.read<CounterCubit>().increment() 调用 Cubitincrement 方法,更新状态。

使用 Stream 处理复杂状态流

BLoC 中,Stream 是核心工具,用于传递状态更新。我们可以将用户的输入事件(如点击按钮)作为 Stream 的输入,并将业务逻辑的输出作为状态流输出给 UI。

示例:BLoC 处理多种事件

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

// 定义事件
abstract class CounterEvent {}

class Increment extends CounterEvent {}
class Decrement extends CounterEvent {}

// 定义 BLoC 类
class CounterBloc extends Bloc<CounterEvent, int> {
  CounterBloc() : super(0);

  
  Stream<int> mapEventToState(CounterEvent event) async* {
    if (event is Increment) {
      yield state + 1;
    } else if (event is Decrement) {
      yield state - 1;
    }
  }
}

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

class MyApp 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(
      app

Bar: AppBar(
        title: Text('BLoC Stream Example'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('You have pushed the button this many times:'),
            BlocBuilder<CounterBloc, int>(
              builder: (context, count) {
                return Text(
                  '$count',
                  style: Theme.of(context).textTheme.headline4,
                );
              },
            ),
          ],
        ),
      ),
      floatingActionButton: Row(
        mainAxisAlignment: MainAxisAlignment.end,
        children: <Widget>[
          FloatingActionButton(
            onPressed: () {
              context.read<CounterBloc>().add(Increment());
            },
            tooltip: 'Increment',
            child: Icon(Icons.add),
          ),
          SizedBox(width: 10),
          FloatingActionButton(
            onPressed: () {
              context.read<CounterBloc>().add(Decrement());
            },
            tooltip: 'Decrement',
            child: Icon(Icons.remove),
          ),
        ],
      ),
    );
  }
}

代码解析

  1. 事件类型CounterEvent 是事件基类,IncrementDecrement 是具体事件。

  2. CounterBlocBLoC 类负责接收事件,并使用 mapEventToState 方法将事件映射为状态更新流。

  3. BlocProviderBlocBuilder:与之前的 Cubit 示例类似,BlocProvider 提供 CounterBloc 实例,BlocBuilder 监听状态流并更新 UI。


总结

通过本教程的学习,你已经掌握了 RiverpodBLoC 这两种高级状态管理框架。这两种框架都适用于大型项目中的复杂状态管理,能够有效地将业务逻辑与 UI 分离,并通过响应式编程处理状态流。

  • Riverpod 适合类型安全、灵活的状态管理需求,提供简单易用的 API。
  • BLoC 则非常适合需要严格分离业务逻辑和 UI 的项目,特别是在需要处理复杂状态流和多种事件的情况下。

掌握这些工具,将帮助你在实际项目中更加高效地管理复杂状态,构建出高质量的 Flutter 应用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2223716.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Navicat 安装

Navicat 安装步骤

qt 下载安装

1. 官网地址 https://www.qt.io/ 2. 下载 使用邮箱注册账号&#xff0c;登录&#xff0c;后边安装时也用的到 登录后&#xff1a; 这里需要电话号验证&#xff0c;电话号需要正确的&#xff0c;其他随便填&#xff0c;电话号中国区前需要86&#xff0c; 验证后自动下载 …

[CSP-J 2023] 一元二次方程(模拟)

变态的大模拟…… 洛谷题目传送门https://www.luogu.com.cn/problem/P9750 解题思路 主要还是模拟&#xff0c;题目让你求啥你就求啥&#xff0c;要注意细节。 然后化简根式的可以用质因数分解一下即可。 代码 #include<bits/stdc.h> using namespace std; #define …

opencv 图像翻转- python 实现

在做图像数据增强时会经常用到图像翻转操作 flip。 具体代码实现如下&#xff1a; #-*-coding:utf-8-*- # date:2021-03 # Author: DataBall - XIAN # Function: 图像翻转import cv2 # 导入OpenCV库path test.jpgimg cv2.imread(path)# 读取图片 cv2.namedWindow(image,1) …

C++基础与实用技巧第三节:内存管理与性能优化

第二章&#xff1a;C基础与实用技巧 第三节&#xff1a;内存管理与性能优化 1. 动态内存的管理策略与技巧 动态内存管理是C编程的核心部分之一&#xff0c;合理管理内存可以极大提高程序的性能和稳定性。在C中&#xff0c;动态内存的分配和释放通常使用new和delete运算符&am…

LeetCode_2427. 公因子的数目_java

1、题目 2427. 公因子的数目https://leetcode.cn/problems/number-of-common-factors/ 给你两个正整数 a 和 b &#xff0c;返回 a 和 b 的 公 因子的数目。 如果 x 可以同时整除 a 和 b &#xff0c;则认为 x 是 a 和 b 的一个 公因子 。 示例 1&#xff1a; 输入&#x…

基于springboot企业微信SCRM管理系统源码带本地搭建教程

系统是前后端分离的架构&#xff0c;前端使用Vue2&#xff0c;后端使用SpringBoot2。 技术框架&#xff1a;SpringBoot2.0.0 Mybatis1.3.2 Shiro swagger-ui jpa lombok Vue2 Mysql5.7 运行环境&#xff1a;jdk8 IntelliJ IDEA maven 宝塔面板 系统与功能介绍 基…

实现prometheus+grafana的监控部署

直接贴部署用的文件信息了 kubectl label node xxx monitoringtrue 创建命名空间 kubectl create ns monitoring 部署operator kubectl apply -f operator-rbac.yml kubectl apply -f operator-dp.yml kubectl apply -f operator-crd.yml # 定义node-export kubectl app…

RHCE的练习(4)

多端口访问多网站 第一步&#xff1a; 关闭防火墙&#xff08;因为要与外部连接访问&#xff09; [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0第二步&#xff1a; 创建新IP地址&#xff08;用于区分&#xff09; [rootlocalhost ~]# nmcli…

【南方科技大学】CS315 Computer Security 【Lab6 IoT Security and Wireless Exploitation】

目录 Introduction (Part 1: OS Security for IoT )Software RequirementsStarting the Lab 6 Virtual MachineSetting up the Zephyr Development EnvironmentDownload the Zephyr Source CodeInstalling Requirements and DependenciesSetting the Project’s Environment Va…

PoissonRecon学习笔记

1. Screened Poisson Reconstruction (SPR) 源码&#xff1a;https://github.com/mkazhdan/PoissonRecon However, as noted by several researchers, it suffers from a tendency to over-smooth the data. 泊松重建存在过度平滑的现象。 方法&#xff1a;position and gradi…

为Windows Terminal 配置zsh + Oh-My-Zsh!

参考&#xff1a; 为Windows Terminal 配置zsh Oh-My-Zsh! [非WSL] https://zhuanlan.zhihu.com/p/625583037 Package: zsh - MSYS2 Packages 安装配置 1、安装 Windows Terminal(必须) Method 1: 打开 Microsoft Store&#xff0c;搜索 “Windows Terminal”。点击 “…

Web应用框架-Django应用基础

1. 认识Django Django是一个用Python编写的开源高级Web框架&#xff0c; 旨在快速开发可维护和可扩展的Web应用程序。 使用Django框架的开发步骤&#xff1a; 1.选择合适的版本 2.安装及配置 3.生成项目结构 4.内容开发 5.迭代、上线、维护 Django官网&#xff1a; Djang…

开源表单生成器OpnForm

什么是 OpnForm &#xff1f; OpnForm 是一个开源的表单构建工具&#xff0c;旨在简化创建自定义表单的过程&#xff0c;特别适合无编码知识的用户。它通过人工智能优化表单创建流程&#xff0c;支持多种用途&#xff0c;如联系人表单、调查表等。OpnForm 提供了一个直观的拖放…

最优化方法-无约束优化算法(最速下降法)matlab实现

一、前言 最速下降法 &#xff0c;又称为梯度法&#xff0c;是一种无约束求解多元函数极小值的方法。最速下降法的起源可以追溯到19世纪&#xff0c;最早由数学家Cauchy在1847年提出。随着计算机技术的发展&#xff0c;最速下降法在20世纪50年代逐渐应用于各种优化问题&#x…

BD数字化装备车场:RFID技术的突破之道

传统的车库管理流程主要依赖手工方式&#xff0c;这无疑降低了作业效率&#xff0c;尤其在任务高峰期或紧急情况下&#xff0c;车库进出口的交通堵塞问题尤为突出。随着2023年的到来&#xff0c;我国相继发布了《交通强国建设纲要》与《数字中国建设整体布局规划》等关键政策文…

Uni-App-01

HBuilder安装卸载 安装 下载HBuilder最新版 解压到安装目录&#xff0c;路径中不要有中文和空格 在桌面上增加快捷方式 卸载 执行reset.bat 删除HBuilder文件夹&#xff08;如果提示文件被占用&#xff0c;杀死相关进程再删除&#xff09; 夜神模拟器安装 安装 下…

Flutter项目打包ios, Xcode 发布报错 Module‘flutter barcode_scanner‘not found

报错图片 背景 flutter 开发的 apple app 需要发布新版本&#xff0c;但是最后一哆嗦碰到个报错&#xff0c;这个小问题卡住了我一天&#xff0c;之间的埪就不说了&#xff0c;直接说我是怎么解决的&#xff0c;满满干货 思路 这个报错 涉及到 flutter_barcode_scanner; 所…

智能园艺:Spring Boot植物健康系统

1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及&#xff0c;互联网成为人们查找信息的重要场所&#xff0c;二十一世纪是信息的时代&#xff0c;所以信息的管理显得特别重要。因此&#xff0c;使用计算机来管理植物健康系统的相关信息成为必然。开发合适…

《面向对象系统分析与设计》三级项目

文章目录 一、项目总体要求<设计模式应用>第一次文档要求第二次文档要求 二、示例第一次文档 - 设计原则应用1、题目描述2、设计:(1&#xff09;优化理由陈述(2&#xff09;类图(3)实现代码 第二次文档 - 设计模式应用1、题目描述2、设计:(1) 优化理由陈述(2&#xff09;…