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

一、使用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.mzph.cn/news/732316.shtml

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

相关文章

软件测试 —— 如何测试图片上传功能?

作为一名专业的软件测试人员&#xff0c;测试图片上传功能是一个重要的任务&#xff0c;以下是一些测试该功能的常用方法&#xff1a; 1. 上传功能测试&#xff1a;确保图片上传功能正常工作&#xff0c;包括选择图片文件、点击上传按钮、上传进度显示、上传成功/失败的提示等。…

JavaWeb03-HTTP协议,Tomcat,Servlet

目录 一、HTTP协议 1.概述 2.特点 3.请求数据格式 &#xff08;1&#xff09;请求行 &#xff08;2&#xff09;请求头 &#xff08;3&#xff09;请求体 &#xff08;4&#xff09;常见请求头 &#xff08;5&#xff09;GET和POST请求区别 4.响应数据格式 &#xf…

gRPC-第二代rpc服务

在如今云原生技术的大环境下&#xff0c;rpc服务作为最重要的互联网技术&#xff0c;蓬勃发展&#xff0c;诞生了许多知名基于rpc协议的框架&#xff0c;其中就有本文的主角gRPC技术。 一款高性能、开源的通用rpc框架 作者作为一名在JD实习的Cpper&#xff0c;经过一段时间的学…

Flask python开发篇: 写一个简单的接口

第一步&#xff1a;新建flask项目 参考使用pycharm新建一个项目 打开pycharm&#xff0c;根据下面图中箭头顺序&#xff0c;新建一个flask的项目&#xff1b; 第二步&#xff1a;运行项目&#xff0c; 安装成功以后&#xff0c;会有个app.py文件&#xff0c;打开以后&#…

qt一个项目有且只有有一个maindow,其他小窗口用QWidget,QDialog是带有yes和no的QWidget

QMaindow QWidget QDialog区别很大 我想要在生成一个小窗口&#xff0c;结果选择基类为maindow&#xff0c;应该是QWidget 然后就出现奇奇怪怪的问题 QMaindow和QWidget不能乱选择&#xff0c;而且各自QPaintEvent也有很多区别 以下就是错误&#xff1a; 我继承maindow的基类…

【物联网设备端开发】物联网设备上云提供开箱即用接入SDK

&#x1f308; 个人主页&#xff1a;帐篷Li &#x1f525; 系列专栏&#xff1a;物联网设备端开发 &#x1f4aa;&#x1f3fb; 物联网设备上云提供开箱即用接入SDK 目录 一、项目介绍 二、项目目录 三、集成方式 四、设备功能开发 4.1 连接与消息 4.2 业务功能 4.3 运维…

云服务器实例重启后,各个微服务的接口(涉及mysql操作的)都用不了了

问题描述&#xff1a; 云服务器被黑客植入挖矿。重启云服务器实例后得到解决&#xff0c;接着把docker&#xff08;zookeeper、redis啥的&#xff09;还有后端jar包啥的都重启了&#xff0c;然后发现后端接口访问不了&#xff0c;只有不涉及数据库操作的接口正常访问&#xff…

【毕业】 医药药店销售管理系统

1、引言 设计结课作业,课程设计无处下手&#xff0c;网页要求的总数量太多&#xff1f;没有合适的模板&#xff1f;数据库&#xff0c;java&#xff0c;python&#xff0c;vue&#xff0c;html作业复杂工程量过大&#xff1f;毕设毫无头绪等等一系列问题。你想要解决的问题&am…

自动驾驶革命:解密端到端背后的数据、算力和AI奇迹

作者 |毫末智行数据智能科学家 贺翔 编辑 |祥威 最近&#xff0c;特斯拉FSD V12的发布引发了业界对端到端自动驾驶的热议&#xff0c;业界纷纷猜测FSD V12的强大能力是如何训练出来的。从马斯克的测试视频可以大致归纳一下FSD V12系统的一些核心特征&#xff1a; 训练数据&am…

防御保护第七次作业-IPSEC VPPN实验

&#xff08;场景选用点到点&#xff0c;配置好FW1的出接口地址和对端FW3的接口地址&#xff0c;认证方式选用预共享密钥&#xff0c;身份认证选用IP地址&#xff09; 1、FW1 IP Sec策略配置 IKE参数配置&#xff1a; IP Sec参数&#xff1a; FW2配置&#xff1a; 加密数据流配…

【附教程】2024,人工智能+AI绘画,看这里就够了~14款主流图像生成软件工具总有一个适合你

AI绘画技术通过深度学习和处理海量图像数据&#xff0c;能够迅速将文字描述转化为富有创意和艺术性的画作。这一技术不仅极大地提升了艺术家的创作效率和作品质量&#xff0c;还为他们提供了全新的灵感来源和创作方式&#xff0c;推动了艺术领域的创新与发展。 同时&#xff0…

力扣代码学习日记八

文章目录 思路解题方法复杂度代码 Problem: 1502. 判断能否形成等差数列 思路 给你一个数字数组 arr 。 如果一个数列中&#xff0c;任意相邻两项的差总等于同一个常数&#xff0c;那么这个数列就称为 等差数列 。 如果可以重新排列数组形成等差数列&#xff0c;请返回 true &a…

Redis持久化:RDB和AOF

RDB&#xff08;Redis DataBase&#xff09; AOF&#xff08;Append Only File&#xff09; AOF重写 RDB AOF 混合持久化 开启 RDB 持久化&#xff1a; RDB 是默认启用的&#xff0c;但你可以检查并设置相关参数以满足你的需求&#xff0c;例如更改保存间隔时间、数据库大…

接口自动化测试框架搭建:基于python+requests+pytest+allure实现

众所周知&#xff0c;目前市面上大部分的企业实施接口自动化最常用的有两种方式&#xff1a; 1、基于代码类的接口自动化&#xff0c;如&#xff1a; PythonRequestsPytestAllure报告定制 2、基于工具类的接口自动化&#xff0c;如&#xff1a; PostmanNewmanJenkinsGit/svnJme…

c++0305习题

一、求下面表达式的值 1&#xff0e;0 2&#xff0e;-1 3&#xff0e;1 4&#xff0e;&#xff08;1&#xff09;1 &#xff08;2&#xff09;3.2 &#xff08;3&#xff09;0 &#xff08;4&#xff09;7.0 5.&#xff08;1&#xff09;0&#xff08;2&#xff09;300.005&a…

python中lambda简介及用法

什么是lambda&#xff1f; lambda是python中的一个关键字&#xff0c;它用于创建匿名函数&#xff0c;也就是没有名字的函数。lambda函数通常用于一些简单的操作&#xff0c;比如作为参数传递给其他函数&#xff0c;或者作为返回值返回给调用者。lambda函数的语法如下&#xf…

记录tensorflow cpu版本安装

已有&#xff1a;anaconda环境 创建虚拟环境 conda create -n tf_cpu python3.9.0 进入虚拟环境 activate tf_cpu 可以选择设置下载源 # 查看当前下载源 conda config --show-sources # 添加下载源 # 清华镜像源 conda config --add channels https://mirrors.tuna.tsing…

数据结构面试问题

数据结构是计算机科学中一个非常重要的基础知识,在面试中也经常会被问到。本文将详细介绍几种常见数据结构的面试题,并给出代码示例,希望对大家准备面试有所帮助。 一、数组和字符串 1. 如何反转一个字符串? 最简单的方法是使用双指针,一个指向字符串开头,一个指向结尾,然后…

Ubuntu 18.04安装最新版Visual Studio Code(VS Code)报依赖库版本过低错误

Ubuntu 18.04安装最新版Visual Studio Code&#xff08;VS Code&#xff09;报依赖库版本过低错误 1. 问题描述2. 解决方案2.1 修复之前安装的错误2.2 安装VS Code 1.85.2 3. 原因分析 1. 问题描述 在Ubuntu 18.04系统上安装VS Code ≥ v1.86.2&#xff08;测试到v1.87.1&…

laravel 模型多对多,应用

laravel 模型多对多&#xff0c;应用&#xff0c;试卷 跟 区域 多对多关系 一个试卷可以发放到a b c 区域 创建试卷表 CREATE TABLE exams (exam_id int(11) unsigned NOT NULL AUTO_INCREMENT,exam_title varchar(100) NOT NULL DEFAULT COMMENT 标题,created_time int(11…