[Flutter]使用Provider进行状态管理

news/2024/4/15 3:50:20/文章来源:https://blog.csdn.net/u012881779/article/details/136556092

一、使用Provider进行状态管理的基本用法

Provider是Flutter中一个非常流行的状态管理工具,它可以帮助开发者更有效地管理Widget树中的数据。Provider的核心思想是将数据模型放置在Widget树中可以被多个子Widget访问的地方,而不必通过构造函数手动传递。

1.添加provider依赖

dependencies:flutter:sdk: flutterprovider: ^6.0.0  

2.创建一个数据模型

import 'package:flutter/material.dart';class CounterModel with ChangeNotifier {int _count = 0;int get count => _count;void increment() {_count++;notifyListeners(); // 通知监听者数据改变}
}

3.在应用中提供模型

在你的应用中,你需要在一个合适的位置(如MaterialApp的上方)使用ChangeNotifierProvider来创建并提供CounterModel的实例。

import 'package:provider/provider.dart';void main() {runApp(// 注意:ChangeNotifierProvider要包装在MaterialApp之外ChangeNotifierProvider(create: (context) => CounterModel(),child: MyApp(),),);
}class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(home: HomeScreen(),);}
}

4.使用ConsumerProvider.of读取和显示数据

在你的HomeScreen中,你可以使用ConsumerProvider.of来读取CounterModel的数据,并构建UI。

class HomeScreen extends StatelessWidget {@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text('Provider Example'),),body: Center(// 使用Consumer来监听CounterModelchild: Consumer<CounterModel>(builder: (context, counter, child) => Text('${counter.count}'),),),floatingActionButton: FloatingActionButton(onPressed: () {// 不需要监听改变时,可以直接使用Provider.of来访问模型Provider.of<CounterModel>(context, listen: false).increment();},child: Icon(Icons.add),),);}
}

当你点击浮动按钮时,increment方法会被调用,CounterModel中的计数器会增加,并通过notifyListeners通知Consumer重新构建,这样UI上显示的数字就会更新。

注意:

  • 使用Provider.of(context)时,如果你不需要监听变化,可以设置listen: false,这样可以提高性能。
  • 当模型更新时,只有通过Consumer或者Provider.of(context)(并且listen设置为true)获取模型的Widget才会重新构建。

二、管理多个不同的状态

如果你有多个不同的状态需要管理,你通常会为每种状态创建不同的模型。每个模型专注于管理一组相关的状态数据和行为。这样可以帮助你保持代码的清晰和分离关注点,使得每个模型都保持简单和专注。

但是,如果你的状态数据非常紧密相关,并且它们通常一起改变,那么将它们放在同一个模型中也是有意义的。

1.创建多个模型

计数器模型
class CounterModel with ChangeNotifier {int _count = 0;int get count => _count;void increment() {_count++;notifyListeners();}
}
主题色彩模型
class ThemeModel with ChangeNotifier {ThemeData _themeData = ThemeData.light();ThemeData get themeData => _themeData;void toggleTheme() {_themeData = _themeData == ThemeData.light() ? ThemeData.dark() : ThemeData.light();notifyListeners();}
}

2.同时管理多个状态

在你的应用中,你可以使用MultiProvider来同时提供多个模型:

void main() {runApp(MultiProvider(providers: [ChangeNotifierProvider(create: (context) => CounterModel()),ChangeNotifierProvider(create: (context) => ThemeModel()),],child: MyApp(),),);
}

你现在可以根据ThemeModel提供的主题数据来构建你的应用程序:

class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return Consumer<ThemeModel>(builder: (context, themeModel, child) {return MaterialApp(theme: themeModel.themeData,home: HomeScreen(),);},);}
}

这样,你就可以在HomeScreen或者其他任何Widget中分别访问和操作CounterModelThemeModel了。通过这种方式,你可以将应用的不同部分的状态管理分离开来,从而使你的代码更加模块化和可维护。

三、异步获取状态

有时,我们不想在模型内部中直接管理状态,而是每次修改SharedPreferences中的缓存数据,以及直接从SharedPreferences获取状态。更进一步,比如异步从网络获取状态,也是类似的。

比如,我们要管理一个订阅状态。

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';class SubscriptionStatusModel extends ChangeNotifier {// 订阅状态的异步读取方法Future<bool> get isSubscribed async {final prefs = await SharedPreferences.getInstance();return prefs.getBool('isSubscribeValid') ?? false;}// 更新SharedPreferences中的订阅状态Future<void> updateSubscriptionStatus(bool newStatus) async {final prefs = await SharedPreferences.getInstance();await prefs.setBool('isSubscribeValid', newStatus);notifyListeners();  // 通知监听器可能有变化}}

在上面的代码中,isSubscribed 现在是一个异步 getter,每次调用时都会从 SharedPreferences 中读取订阅状态。updateSubscriptionStatus 方法现在会将新状态写入 SharedPreferences 并通知监听器。

这样修改后,你就需要在UI中相应地处理Future。例如,如果你在一个widget中使用这个模型,你可能需要使用 FutureBuilder

FutureBuilder<bool>(future: provider.isSubscribed, // 假设` provider `是你的SubscriptionStatusModel实例builder: (context, snapshot) {if (snapshot.connectionState == ConnectionState.waiting) {// 等待数据时返回加载指示器return CircularProgressIndicator();} else if (snapshot.hasError) {// 处理错误情况return Text('Error: ${snapshot.error}');} else {// 使用订阅状态来构建widgetbool isSubscribed = snapshot.data ?? false;return Text(isSubscribed ? 'Subscribed' : 'Not subscribed');}},
)

实际用例:

Stack(alignment: Alignment.center,children: [CustomScrollView(// ...),Consumer<SubscriptionStatusModel>(builder: (context, provider, child) {return FutureBuilder<bool>(future: provider.isSubscribed,  builder: (context, snapshot) {if (snapshot.connectionState == ConnectionState.waiting) {// 等待数据时返回加载指示器// return CircularProgressIndicator();return SizedBox.shrink();} else if (snapshot.hasError) {// 处理错误情况// return Text('Error: ${snapshot.error}');return SizedBox.shrink();} else {// 使用订阅状态来构建widgetbool isSubscribed = snapshot.data ?? false;return Visibility(visible: !isSubscribed,child: Positioned(left: 0,right: 0,bottom: 16,child: _subscribeButton(),),);}},);}),],
),

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

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

波卡 Alpha 计划启动,呼唤先锋创新者重新定义 Web3 开发

原文&#xff1a;https://polkadot.network/blog/the-polkadot-alpha-program-a-new-era-for-decentralized-building-collaboration/ 编译&#xff1a;OneBlock 区块链领域不断发展&#xff0c;随之而来的是发展和创新机会的增加。而最新里程碑是令人振奋的 Polkadot Alpha …

鸿蒙Harmony应用开发—ArkTS声明式开发(触摸交互控制:触摸热区设置)

适用于支持通用点击事件、通用触摸事件、通用手势处理的组件。 说明&#xff1a; 从API Version 8开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 responseRegion responseRegion(value: Array<Rectangle> | Rectangle) 设置一个或…

UI自动化测试使用场景及脚本录制

经常有人会问&#xff0c;什么样的项目才适合进行UI自动化测试呢&#xff1f;UI自动化测试相当于模拟手工测试&#xff0c;通过程序去操作页面上的控件。而在实际测试过程中&#xff0c;经常会遇到无法找到控件&#xff0c;或者因控件定义变更而带来的维护成本等问题。 哪些场…

《UE5_C++多人TPS完整教程》学习笔记26 ——《P27 在线会话测试(Testing An Online Session)》

本文为B站系列教学视频 《UE5_C多人TPS完整教程》 —— 《P27 在线会话测试&#xff08;Testing An Online Session&#xff09;》 的学习笔记&#xff0c;该系列教学视频为 Udemy 课程 《Unreal Engine 5 C Multiplayer Shooter》 的中文字幕翻译版&#xff0c;UP主&#xff0…

K8s-MySQL主从集群

K8s-MySQL主从集群 引言 该案例代码均可从https://github.com/WeiXiao-Hyy/k8s_example 获取&#xff0c;欢迎Star&#xff01; 需求 一个“主从复制”的MySQL集群有一个主节点Master有多个从节点Slave从节点需要能水平扩展所以写操作只能在主节点上执行读操作可以在所有节点…

ACM32系列 MCU安全特性概述

随着物联网的发展&#xff0c;智能化产品的不断涌现&#xff0c;信息安全问题也日渐受到关注。因此&#xff0c;通用安全MCU产品也应运而生&#xff0c;能够更好地帮助客户在其产品设计中加强安全性&#xff0c;助力IoT的应用创新。 本文将详细介绍ACM32系列 MCU的安全特性。 …

【Linux进阶之路】网络 —— “?“ (下)

文章目录 前言一、概念铺垫1.TCP2.全双工 二、网络版本计算器1. 原理简要2. 实现框架&&代码2.1 封装socket2.2 客户端与服务端2.3 封装与解包2.4 请求与响应2.5 对数据进行处理2.6 主程序逻辑 3.Json的简单使用 总结尾序 前言 在上文我们学习使用套接字的相关接口进行了…

面试经典150题【61-70】

文章目录 面试经典150题【61-70】61.旋转链表86.分隔链表104. 二叉树的最大深度100.相同的树226.翻转二叉树101.对称二叉树105.从前序与中序遍历序列构造二叉树106.从后序和中序遍历序列构造二叉树117.填充每个节点的下一个右侧节点指针II114.二叉树展开为链表 面试经典150题【…

怎么把视频变成gif动图?一招在线生成gif动画

MP4是一种常见的视频文件格式&#xff0c;它是一种数字多媒体容器格式&#xff0c;可以用于存储视频、音频和字幕等多种媒体数据。MP4格式通常用于在计算机、移动设备和互联网上播放和共享视频内容。要将MP4视频转换为GIF格式&#xff0c;您可以使用专门的视频转gif工具。这个工…

【Linux】第一个小程序--进度条

这篇博客要综合利用以前的知识&#xff0c;来实现一个进度条程序~ 目录 换行&回车 缓冲区 实现简单的倒计时 实现进度条 version1 version2 在开始写这个小程序之前&#xff0c;我们先学习一些预备知识&#xff1a; 换行&回车 缓冲区 在我们运行这个程序时&…

生活的色彩--爱摸鱼的美工(17)

题记 生活不如意事十之八九&#xff0c; 恶人成佛只需放下屠刀&#xff0c;善人想要成佛却要经理九九八十一难。而且历经磨难成佛的几率也很小&#xff0c;因为名额有限。 天地不仁以万物为刍狗&#xff01; 小美工记录生活&#xff0c;记录绘画演变过程的一天。 厨房 食…

Linux系统安装Dashy服务结合内网穿透实现公网访问本地导航页

文章目录 简介1. 安装Dashy2. 安装cpolar3.配置公网访问地址4. 固定域名访问 简介 Dashy 是一个开源的自托管的导航页配置服务&#xff0c;具有易于使用的可视化编辑器、状态检查、小工具和主题等功能。你可以将自己常用的一些网站聚合起来放在一起&#xff0c;形成自己的导航…

【“双碳”目标】Acrel-2000Z分布式光伏发电监测系统解决方案

1 概述 “十四五”期间&#xff0c;随着“双碳”目标提出及逐步落实&#xff0c;本就呈现出较好发展势头的分布式光伏发展有望大幅提速。就“十四五”光伏发展规划&#xff0c;国家发改委能源研究所可再生能源发展中心副主任陶冶表示&#xff0c;“双碳”目标意味着国家产业结…

TimescaleDB 开源时序数据库

文章目录 1.TimescaleDB介绍2.Hypertable 和 chunk3.Hypertable4.Hypertable操作 开源中间件 # TimescaleDBhttps://iothub.org.cn/docs/middleware/ https://iothub.org.cn/docs/middleware/timescale/timescale-summary/1.TimescaleDB介绍 TimescaleDB是基于PostgreSQL数据…

JavaWeb——014SpringBoot原理(配置优先级、Bean管理、SpringBoot原理)

SpingBoot原理 目录 SpingBoot原理1. 配置优先级2. Bean管理2.1 获取Bean2.2 Bean作用域2.3 第三方Bean 3. SpringBoot原理3.1 起步依赖3.2 自动配置3.2.1 概述3.2.2 常见方案3.2.2.1 概述3.2.2.2 方案一3.2.2.3 方案二 3.2.3 原理分析3.2.3.1 源码跟踪3.2.3.2 Conditional 3.2…

Media Encoder 2024:未来媒体编码的新纪元 mac/win版

随着科技的飞速发展&#xff0c;媒体内容已成为我们日常生活中不可或缺的一部分。为了满足用户对高质量视频内容不断增长的需求&#xff0c;Media Encoder 2024应运而生&#xff0c;它凭借卓越的技术和创新的特性&#xff0c;重塑了媒体编码的未来。 Media Encoder 2024软件获…

Flutter学习9 - http 中 get/post 请求示例

1、配置 http pubspec.yaml dependencies:http: ^0.13.4flutter:sdk: flutterhttp 库最新插件版本查看&#xff1a;https://pub.dev/packages/http不一定要用最新版本 http&#xff0c;要使用项目所能支持的版本 .dart import package:http/http.dart as http;2、示例 &a…

VsCode中使用Anaconda中的python环境

1、今天在新的电脑上安装了VsCode和Anaconda&#xff0c;但是在VsCode却选择不了python的环境&#xff0c;期望结果是下面这样的 2、接着在网上百度&#xff0c;找到了方法&#xff0c;具体方法如下&#xff1a; 2.1需要先在Extensions中安装python 2.2再使用ctrlshiftP后使用…

分布式数据库 GaiaDB-X 金融应用实践

1 银行新一代核心系统建设背景及架构 在银行的 IT 建设历程中&#xff0c;尤其是中大行&#xff0c;大多都基于大型机和小型机来构建核心系统。随着银行业务的快速发展&#xff0c;这样的系统对业务的支持越来越举步维艰&#xff0c;主要体现在以下四个方面&#xff1a; 首先是…

日韩媒体宣传案例分析:CloudNEO 为您提供海外媒体宣传最佳途径

近年来&#xff0c;随着互联网的迅速发展和全球化的加速推进&#xff0c;海外市场对于企业的重要性日益凸显。尤其是在亚洲地区&#xff0c;日本和韩国作为亚洲最具活力和潜力的市场之一&#xff0c;成为众多企业争相开拓的目标。在这个过程中&#xff0c;媒体宣传不仅是企业推…