代码

class Example extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Example"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// 使用Consumer部件获取UserModel实例并订阅其变化
Consumer<UserModel>(
builder: (_, userModel, child) {
// 在数据更新时,重新构建子部件,并显示userModel的name属性
return Text(userModel.name,
style: const TextStyle(
color: Colors.red,
fontSize: 30
)
);
},
),
// 使用Consumer部件获取UserModel实例并订阅其变化
Consumer<UserModel>(
builder: (_, userModel, child) {
// 在数据更新时,重新构建子部件,并显示一个按钮,点击按钮会调用changeName方法改变name的值
return Padding(
padding: const EdgeInsets.all(20),
child: ElevatedButton(
onPressed: (){
userModel.changeName();
},
child: const Text("改变值"),
),
);
},
),
],
),
),
);
}
}

1、Provider:

通用的提供者,可用于共享任何对象,不仅仅是状态对象。在更新时,提供者会重新构建依赖于该对象的部件。

创建模型
//1 最基本的Provider组件,可以使用它为组件树中的任何位置提供值,
//组件但是当该值更改的时候,它并不会更新UI
class UserModel extends ChangeNotifier {
String name = "jimi"; void changeName(){
name = "hellp";
print(name);
}
}
应用程序入口设置
class MyApp9 extends StatelessWidget {
const MyApp9({super.key}); @override
Widget build(BuildContext context) {
return Provider<UserModel>(
create: (_) =>UserModel(),
child: MaterialApp(
debugShowCheckedModeBanner: false,
home: Example(),
),
);
}
}

2、* ChangeNotifierProvider:

用于将一个ChangeNotifier对象共享给其子孙节点,并监听状态变化。会监听模型对象的变化,而且当数据改变时,它也会重建Consumer(消费者)

创建模型
//2.ChangeNotifierProvider 它跟Provider组件不同,
//ChangeNotifierProvider会监听模型对象的变化,而且当数据改变时,
//它也会重建Consumer(消费者)
class UserModel with ChangeNotifier { String name = "Jimi"; void changeName() {
name = "hello";
notifyListeners();
}
}
应用程序入口设置
class MyApp9 extends StatelessWidget {
const MyApp9({super.key}); @override
Widget build(BuildContext context) {
return ChangeNotifierProvider<UserModel>(
create: (_) =>UserModel(),
child: MaterialApp(
debugShowCheckedModeBanner: false,
home: Example(),
), );
}
}
更新数据的使用(监听数据的变化)
    void monitor() {
// 监听 Provider 参数变化
Provider.of<Parameter>(context, listen: false).addListener(() {
bookId = Provider.of<Parameter>(context, listen: false).bookId;
letterId = Provider.of<Parameter>(context, listen: false).letterId;
VTid = Provider.of<Parameter>(context, listen: false).VTid;
fetchDataFromAPI(bookId, letterId,VTid);
}); // 初始化获取数据和更新页面
bookId = Provider.of<Parameter>(context, listen: false).bookId;
letterId = Provider.of<Parameter>(context, listen: false).letterId;
VTid = Provider.of<Parameter>(context, listen: false).VTid; fetchDataFromAPI(bookId, letterId,VTid);
}

3、FutureProvider:

用于共享Future对象,通常在异步操作和数据加载中使用。

  • FutureProvider只会重建一次
  • 默认显示初始值
  • 然后显示Future
  • 最后不会再次重建
创建模型
class UserModel {

  UserModel({required this.name});

  String name = "Jimi";

  Future<void> changeName() async {
print(name);
await Future.delayed(const Duration(milliseconds: 2000)); //模拟网络请求延迟两秒后改变其值
name = "hello";
print(name);
}
}
class UserFuture {
Future<UserModel> asyncGetUserModel2() async {
await Future.delayed(const Duration(milliseconds: 6000));
return UserModel(name: "获取新的数据");
}
}
应用程序入口设置
class MyApp9 extends StatelessWidget {
const MyApp9({super.key}); @override
Widget build(BuildContext context) {
return FutureProvider<UserModel>(
create: (_) =>UserFuture().asyncGetUserModel2(),
initialData: UserModel(name: "hello1"), //必传 不传报错
child: MaterialApp(
debugShowCheckedModeBanner: false,
home: Example(),
),
);
}
}

4、StreamProvider:

用于共享流(Stream)对象,可以是Dart中的任何流。和FutureProvider一样,主要的区别在于值会根据多次触发重新构建UI。

创建模型
//4、StreamProvider提供流值,是围绕StreamBuilder,所提供的值会在传入的时候替换掉新值。
//和FutureProvider一样,主要的区别在于值会根据多次触发重新构建UI。
class UserModel {
UserModel({required this.name});
String name = "Jimi"; void changeName() {
name = "hello";
}
} //每隔一秒钟生成一个数字
class UserStream { Stream<UserModel> getStreamUserModel() {
return Stream<UserModel>.periodic(const Duration(milliseconds: 1000),
(value) => UserModel(name: "$value")
).take(10);
}
}
应用程序入口设置
class MyApp9 extends StatelessWidget {
const MyApp9({super.key}); @override
Widget build(BuildContext context) {
return StreamProvider<UserModel>(
create: (_) => UserStream().getStreamUserModel(),
initialData: UserModel(name: "hello1"), //必传 不传报错
child: MaterialApp(
debugShowCheckedModeBanner: false,
home: Example(),
),
);
}
}

5、* MultiProvider

在实际开发过程中肯定会有多个提供者,我们虽然可以采用嵌套的方式来解决,但是这样无疑是混乱的,

可读性级差。这个时候强大的MultiProvder就产生了;用于在应用程序的根部层次上为子树中的多个小部件提供数据共享;

创建模型
class UserModel1 with ChangeNotifier {

  String name = "Jimi";

  void changeName() {
name = "hello";
notifyListeners();
}
} class UserModel4 with ChangeNotifier { String name = "Jimi";
int age = 18; void changeName() {
name = "hello";
age = 20;
notifyListeners();
}
}
应用程序入口设置
return MultiProvider(
providers: [
ChangeNotifierProvider<UserModel1>(create: (_) => UserModel1()),
ChangeNotifierProvider<UserModel4>(create: (_) => UserModel4()),
/// 添加更多
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
home: MultiProviderExample(),
),
);
使用数据
class MultiProviderExample extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("MultiProviderExample"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Consumer<UserModel1>(
builder: (_, userModel, child) {
return Text(userModel.name,
style: TextStyle(
color: Colors.red,
fontSize: 30
)
);
},
),
Consumer<UserModel4>(
builder: (_, userModel, child) {
return Text(userModel.age.toString(),
style: TextStyle(
color: Colors.green,
fontSize: 30
)
);
},
),
Consumer2<UserModel1, UserModel4>(
builder: (_, userModel1, userModel4, child) {
return Padding(
padding: EdgeInsets.all(20),
child: ElevatedButton(
onPressed: (){
userModel1.changeName();
userModel4.changeName();
},
child: Text("改变值"),
),
);
},
),
],
),
),
);
}
}

6、ProxyProvider:

用于根据其他提供者的值计算新值,并将新值共享给下游部件。

当我们有多个模型的时候,会有模型依赖另一个模型的情况,在这种情况下,

我们可以使用ProxyProvider从另一个提供者获取值,然后将其注入到另一个提供者中。

创建模型
class UserModel5 with ChangeNotifier {

  String name = "Jimi";

  void changeName({required String newName}) {
name = newName;
notifyListeners();
}
} class WalletModel { UserModel5? userModel5; WalletModel({this.userModel5}); void changeName() {
userModel5?.changeName(newName: "JIMI");
}
}
应用程序入口设置
class MyApp9 extends StatelessWidget {
const MyApp9({super.key}); @override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider<UserModel5>(create: (_) => UserModel5()),
ProxyProvider<UserModel5, WalletModel>(
update: (_, userModel5, walletModel) => WalletModel(userModel5: userModel5),
)
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
home: ProxyProviderExample(),
),
);
}
}
使用数据
class ProxyProviderExample extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("ProxyProviderExample"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Consumer<UserModel5>(
builder: (_, userModel, child) {
return Text(userModel.name,
style: const TextStyle(
color: Colors.red,
fontSize: 30
)
);
},
),
Consumer<UserModel5>(
builder: (_, userModel, child) {
return Padding(
padding: EdgeInsets.all(20),
child: ElevatedButton(
onPressed: (){
userModel.changeName(newName: "hello");
},
child: Text("改变值"),
),
);
},
),
Consumer<WalletModel>(
builder: (_, walletModel, child) {
return Padding(
padding: EdgeInsets.all(20),
child: ElevatedButton(
onPressed: (){
walletModel.changeName();
},
child: Text("通过代理改变值"),
),
);
},
),
],
),
),
);
}
}

7、* ChangeNotifierProxyProvider

ProxyProvider原理一样,唯一的区别在于它构建和同步ChangeNotifierChangeNotifierProvider,当提供者数据变化时,将会重构UI。

创建模型

1.

class BookModel {

  static var _books = [
Book(1, "夜的命名数"),
Book(2, "大奉打更人"),
Book(3, "星门"),
Book(4, "大魏读书人"),
Book(5, "我师兄实在太稳健了"),
Book(6, "深空彼岸"),
]; // 获取书籍长度
int get length => _books.length; // 根据ID获取书籍
Book getById(int id) => _books[id -1]; // 根据索引获取数据
Book getByPosition(int position) => _books[position]; // 更多....
} class Book {
final int bookId;
final String bookName; Book(this.bookId, this.bookName);
}

2.

class BookManagerModel with ChangeNotifier {

  // 依赖bookModel
final BookModel _bookModel; // 获取数据所有的ID
List<int>? _bookIds; // 构造函数
BookManagerModel(this._bookModel, {BookManagerModel? bookManagerModel})
: _bookIds = bookManagerModel?._bookIds ?? []; // 获取所有的书
List<Book> get books => _bookIds!.map((id) => _bookModel.getById(id)).toList(); // 根据索引获取数据
Book getByPosition(int position) => books[position]; // 获取书籍的长度
int get length => _bookIds?.length ?? 0; // 添加书籍
void addFaves(Book book) {
_bookIds!.add(book.bookId);
notifyListeners();
} // 删除书籍
void removeFaves(Book book) {
_bookIds!.remove(book.bookId);
notifyListeners();
}
}
复制代码
应用程序入口设置
return MultiProvider(
providers: [
Provider(create: (_) => BookModel()),
ChangeNotifierProxyProvider<BookModel, BookManagerModel>(
create: (_) => BookManagerModel(BookModel()),
update: (_, bookModel, bookManagerModel) => BookManagerModel(bookModel),
)
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
home: ChangeNotifierProxyProviderExample(),
),
);
使用数据

1.

class ChangeNotifierProxyProviderExample extends StatefulWidget {
@override
_ChangeNotifierProxyProviderExampleState createState() => _ChangeNotifierProxyProviderExampleState();
} class _ChangeNotifierProxyProviderExampleState extends State<ChangeNotifierProxyProviderExample> { var _selectedIndex = 0;
var _pages = [PageA(), PageB()]; @override
Widget build(BuildContext context) {
return Scaffold(
body: _pages[_selectedIndex],
bottomNavigationBar: BottomNavigationBar(
currentIndex: _selectedIndex,
onTap: (index) {
setState(() {
_selectedIndex = index;
});
},
items: [
BottomNavigationBarItem(
icon: Icon(Icons.book),
label: "书籍列表"
),
BottomNavigationBarItem(
icon: Icon(Icons.favorite),
label: "收藏"
)
],
),
);
}
}

2.

class PageA extends StatelessWidget {
@override
Widget build(BuildContext context) { var bookModel = Provider.of<BookModel>(context); return Scaffold(
appBar: AppBar(
title: Text("书籍列表"),
),
body: ListView.builder(
itemCount: bookModel.length,
itemBuilder: (_, index) => BookItem(id: index + 1),
),
);
}
}

3.

class PageB extends StatelessWidget {
@override
Widget build(BuildContext context) { var bookManagerModel = Provider.of<BookManagerModel>(context);
var bookCount = bookManagerModel.length; return Scaffold(
appBar: AppBar(
title: Text("收藏列表"),
),
body: ListView.builder(
itemCount: bookCount,
itemBuilder: (_, index) => BookItem(id: bookManagerModel.getByPosition(index).bookId),
),
);
}
}

4.

class BookButton extends StatelessWidget {

  final Book book;

  BookButton({
Key? key,
required this.book
}) : super(key: key); @override
Widget build(BuildContext context) { var bookManagerModel = Provider.of<BookManagerModel>(context); return GestureDetector(
onTap: bookManagerModel.books.contains(this.book)
? () => bookManagerModel.removeFaves(this.book)
: () => bookManagerModel.addFaves(this.book),
child: SizedBox(
width: 100,
height: 60,
child: bookManagerModel.books.contains(this.book)
? Icon(Icons.star, color: Colors.red,)
: Icon(Icons.star_border),
),
);
}
}

5.

class BookItem extends StatelessWidget {

  final int id;

  BookItem({
Key? key,
required this.id
}) : super(key: key); @override
Widget build(BuildContext context) { var bookModel = Provider.of<BookModel>(context);
var book = bookModel.getById(id); return ListTile(
leading: CircleAvatar(
child: Text("${book.bookId}"),
),
title: Text("${book.bookName}",
style: TextStyle(
color: Colors.black87
),
),
trailing: BookButton(book: book),
);
}
}

ListenableProxyProvider:

ListenableProxyProviderListenableProvider的一个变体,但是在使用上和ChangeNotifierProvider效果惊人的一致

此参考于Flutter Provider状态管理---八种提供者使用分析-腾讯云开发者社区-腾讯云 (tencent.com)

Provider的八种提供者的更多相关文章

  1. http 中定义的八种请求的介绍

    在http1.1协议中,共定义了8种可以向服务器发起的请求(这些请求也叫做方法或动作),本文对这八种请求做出简要的介绍: 1.PUT:put的本义是推送 这个请求的含义就是推送某个资源到服务器,相当于 ...

  2. Web开发必知的八种隔离级别

    ACID性质是数据库理论中的奠基石,它定义了一个理论上可靠数据库所必须具备的四个性质:原子性,一致性,隔离性和持久性.虽然这四个性质都很重要,但是隔离性最为灵活.大部分数据库都提供了一些可供选择的隔离 ...

  3. 【转】Java八种基本数据类型的比较及其相互转化

    java中有且仅有八种基本数据类型,记住就行,共分为四类: 第一类:整型-->byte     short      int     long 第二类:浮点-->float    doub ...

  4. Javascript刷新页面的八种方法

    /** * Javascript刷新页面的八种方法 * 说明一下,jQuery没有发现刷新页面的方法. */ 1 history.go(0) 2 location.reload() 3 locatio ...

  5. Selenium Webdriver元素定位的八种常用方式

    楼主原创,欢迎学习和交流,码字不容易,转载请注明出处,谢谢. 在使用selenium webdriver进行元素定位时,通常使用findElement或findElements方法结合By类返回的元素 ...

  6. Linux 的shell 字符串截取很有用。有八种方法。

    一 Linux 的字符串截取很有用.有八种方法. 假设有变量 var=http://www.linuxidc.com/123.htm 1  # 号截取,删除左边字符,保留右边字符. echo ${va ...

  7. Linux下进程通信的八种方法

    Linux下进程通信的八种方法:管道(pipe),命名管道(FIFO),内存映射(mapped memeory),消息队列(message queue),共享内存(shared memory),信号量 ...

  8. Delphi过程函数传递参数的八种方式

    今天一同事问我为什么有些过程函数里面有Var而有些没有,不解,遂到网上百度,得解.快哉,快哉. 在Delphi过程.函数中传递参数几个修饰符为Const.Var.Out.另一种不加修饰符的为默认按值传 ...

  9. 使用八种牛云存储解决方案ios7.1的app部署问题

    使用八种牛云存储解决方案ios7.1的app部署问题 一个.问题叙述性说明 开发完ios版本号的app.须要将.ipa文件和.plist文件打包上传,供用户下载,在线安装.用户安装过程简单描写叙述例如 ...

  10. LVS负载均衡的三种模式和八种算法总结

    三种LVS负载均衡模式 调度器的实现技术中,IP负载均衡技术是效率最高的,IP虚拟服务器软件(IPVS)是在linux内核中实现的。 LVS负载均衡模式---1.NAT模式 NAT用法本来是因为网络I ...

随机推荐

  1. CF433B

    题目简化和分析: 为了更加快速的求出答案,好像没前缀和快速. 为了大家更好的理解线段树,我们使用了线段树. 如果您并不了解线段树,可以转战模板. 因为我们知道线段树可以快速求区间和,于是我们建两棵树. ...

  2. .NET高性能开发-位图索引(一)

    首先来假设这样一个业务场景,大家对于飞机票应该不陌生,大家在购买机票时,首先是选择您期望的起抵城市和时间,然后选择舱等(公务舱.经济舱),点击查询以后就会出现航班列表,随意的点击一个航班,可以发现有非 ...

  3. ABC318 A-G 题解

    A 枚举 \(1\sim n\) 的每个数,判断是否有 \(i-M\equiv 0\pmod P\) 即可. 赛时代码 B 暴力覆盖即可,注意 \(x,y\) 均是左开右闭. 赛时代码 C 贪心的想, ...

  4. SpringBoot如何缓存方法返回值?

    目录 Why? HowDo annotation MethodCache MethodCacheAspect controller SpringCache EnableCaching Cacheabl ...

  5. 怎么用Python写一个浏览器集群框架

    这是做什么用的 框架用途 在采集大量新闻网站时,不可避免的遇到动态加载的网站,这给配模版的人增加了很大难度.本来配静态网站只需要两个技能点:xpath和正则,如果是动态网站的还得抓包,遇到加密的还得j ...

  6. RLChina理论三:强化学习基础

    强化学习基础 马尔可夫决策过程就是在,环境自发做出转变,是个随波逐流的过程,At是智能体的行动,在St环境状态下加入At动作,c才进入下个状态S(t+1),即环境有自己的变化,也加入了智能体的决策. ...

  7. SSL证书链及使用

    什么是证书链 证书链简单来说是域名钥证书.CA公钥.根证书形成的一个颁发链条,属于公钥的一部分. 更白话一点,就是证书链文件包含一系列CA机构公钥的证书. 证书链格式 一般证书链格式是.chain,证 ...

  8. Unity学习笔记--数据持久化之PlayerPrefs的使用

    数据持久化 PlayerPrefs相关 PlayerPrefs是Unity游戏引擎中的一个类,用于在游戏中存储和访问玩家的偏好设置和数据.它可以用来保存玩家的游戏进度.设置选项.最高分数等信息.Pla ...

  9. dbeaver软件的使用

    dbeaver软件的使用 一.dbeaver简介: dbeaver是免费和开源(GPL)为开发人员和数据库管理员通用数据库工具. DBeaver [1] 是一个通用的数据库管理工具和 SQL 客户端, ...

  10. Kubernetes 中的服务注册与发现原理分析

    公众号「架构成长指南」,专注于生产实践.云原生.分布式系统.大数据技术分享. 对k8s有点了解技术人员,应该都只知道k8s是有服务注册发现的,今天就分析下这个原理,看看怎么实现的. 什么是服务注册与发 ...