代码

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. nfls10.1

    T1 大水题,用位运算更加便捷求解. T2 看出来有环了,但是没往基环树上想,寄. 暴力分,有部分分是基础树,可以跑一遍深搜,根节点的选择是 k 种颜色,剩下的是 k - 1 种颜色.还有暴力是可以二 ...

  2. Hugging Face 分词器新增聊天模板属性

    一个幽灵,格式不正确的幽灵,在聊天模型中游荡! 太长不看版 现存的聊天模型使用的训练数据格式各各不同,我们需要用这些格式将对话转换为单个字符串并传给分词器.如果我们在微调或推理时使用的格式与模型训练时 ...

  3. P7072 [CSP-J2020] 直播获奖

    Problem 考查知识点:桶优化. 题目简述 竞赛的获奖率为 \(w\%\),即当前排名前 \(w\%\) 的选手的最低成绩就是即时的分数线. 若当前已评出了 \(p\) 个选手的成绩,则当前计划获 ...

  4. 相邻像素相关性的matlab实现

    目录 加密性能分析(一)相邻像素相关性的matlab实现 相邻像素相关性 (一)概念 (二)相邻像素的相关系数 (三)相邻像素分布图 加密性能分析(一)相邻像素相关性的matlab实现 相邻像素相关性 ...

  5. GitHub Actions 入门指南

    前言 GitHub Actions 可以构建一组自动化的工作流程,并提供了拉取请求.合并分支等事件来触发他们.一般成熟的开源项目会在每个版本发布时提供 releases ,它就是通过 Actions ...

  6. python01-基础概念与环境搭建

    学习目标 了解硬件 & 操作系统 & 软件(应用系统)之间的关系. 了解常见的操作系统都有哪些. 了解编译器和解释器的区别和作用. 了解编程语言进行分类 了解Python解释器的种类 ...

  7. 练习感受以及经验总结(ing)

    connection = DriverManager.getConnection(url, user,password );顺序一定不能搞错,当时顺序写错了.查bug查了一晚上.得益于两个函数都用到了 ...

  8. DataGtip的永久激活方法(Windows2021-2023版本均可)

    一.打开DataGrip 出现以下界面即显示需要激活,否则无法使用,这里打开后点击Exit退出 二.下载激活包 1.下载激活包准备激活 下载链接: 链接:https://pan.baidu.com/s ...

  9. Android OpenGL ES入门

    1.OpenGL 和OpenGL ES OpenGL(Open Graphics Library)是一种用于渲染2D和3D图形的跨平台编程接口.OpenGL提供了一套标准的函数和接口,使开发人员能够在 ...

  10. 带你玩转 Vite + Vue3 高低版本常用玩法

    一.首先来个 Vite 的通用简介 Vite 是一种新型前端构建工具,在我们保险前端项目中已经推动并应用很久了,Vite 能够显著降低构建时间,提升前端开发效率. 它主要由两部分组成: 一个开发服务器 ...