Provider的八种提供者
代码
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原理一样,唯一的区别在于它构建和同步ChangeNotifier的ChangeNotifierProvider,当提供者数据变化时,将会重构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:
ListenableProxyProvider是ListenableProvider的一个变体,但是在使用上和ChangeNotifierProvider效果惊人的一致
此参考于Flutter Provider状态管理---八种提供者使用分析-腾讯云开发者社区-腾讯云 (tencent.com)
Provider的八种提供者的更多相关文章
- http 中定义的八种请求的介绍
在http1.1协议中,共定义了8种可以向服务器发起的请求(这些请求也叫做方法或动作),本文对这八种请求做出简要的介绍: 1.PUT:put的本义是推送 这个请求的含义就是推送某个资源到服务器,相当于 ...
- Web开发必知的八种隔离级别
ACID性质是数据库理论中的奠基石,它定义了一个理论上可靠数据库所必须具备的四个性质:原子性,一致性,隔离性和持久性.虽然这四个性质都很重要,但是隔离性最为灵活.大部分数据库都提供了一些可供选择的隔离 ...
- 【转】Java八种基本数据类型的比较及其相互转化
java中有且仅有八种基本数据类型,记住就行,共分为四类: 第一类:整型-->byte short int long 第二类:浮点-->float doub ...
- Javascript刷新页面的八种方法
/** * Javascript刷新页面的八种方法 * 说明一下,jQuery没有发现刷新页面的方法. */ 1 history.go(0) 2 location.reload() 3 locatio ...
- Selenium Webdriver元素定位的八种常用方式
楼主原创,欢迎学习和交流,码字不容易,转载请注明出处,谢谢. 在使用selenium webdriver进行元素定位时,通常使用findElement或findElements方法结合By类返回的元素 ...
- Linux 的shell 字符串截取很有用。有八种方法。
一 Linux 的字符串截取很有用.有八种方法. 假设有变量 var=http://www.linuxidc.com/123.htm 1 # 号截取,删除左边字符,保留右边字符. echo ${va ...
- Linux下进程通信的八种方法
Linux下进程通信的八种方法:管道(pipe),命名管道(FIFO),内存映射(mapped memeory),消息队列(message queue),共享内存(shared memory),信号量 ...
- Delphi过程函数传递参数的八种方式
今天一同事问我为什么有些过程函数里面有Var而有些没有,不解,遂到网上百度,得解.快哉,快哉. 在Delphi过程.函数中传递参数几个修饰符为Const.Var.Out.另一种不加修饰符的为默认按值传 ...
- 使用八种牛云存储解决方案ios7.1的app部署问题
使用八种牛云存储解决方案ios7.1的app部署问题 一个.问题叙述性说明 开发完ios版本号的app.须要将.ipa文件和.plist文件打包上传,供用户下载,在线安装.用户安装过程简单描写叙述例如 ...
- LVS负载均衡的三种模式和八种算法总结
三种LVS负载均衡模式 调度器的实现技术中,IP负载均衡技术是效率最高的,IP虚拟服务器软件(IPVS)是在linux内核中实现的。 LVS负载均衡模式---1.NAT模式 NAT用法本来是因为网络I ...
随机推荐
- C# 12 中的新增功能
新的 C# 12 功能在预览版中已经引入. 您可以使用最新的 Visual Studio 预览版或最新的 .NET 8 预览版 SDK 来尝试这些功能.以下是一些新引入的功能: 主构造函数 集合表达式 ...
- 如何编写难以维护的 React 代码?耦合通用组件与业务逻辑
在众多项目中,React代码的维护经常变得棘手.其中一个常见问题是:将业务逻辑直接嵌入通用组件中,导致通用组件与业务逻辑紧密耦合,使其失去"通用性".这种做法使通用组件过于依赖具体 ...
- Util应用框架Web Api开发快速入门
本文是使用Util应用框架开发 Web Api 项目快速入门教程. 前面已经详细介绍了环境搭建,如果你还未准备好,请参考前文. 开发流程概述 创建代码生成专用数据库. Util应用框架需要专门用来生成 ...
- docker容器管理脚本
#!/bin/bash #auto install docker and Create VM #by jfedu.net 2017 #Define PATH Varablies IPADDR=`ifc ...
- C#winform软件实现一次编译,跨平台windows和linux兼容运行,兼容Visual Studio原生界面Form表单开发
一.背景: 微软的.net core开发工具,目前来看,winform界面软件还没有打算要支持linux系统下运行的意思,要想让c#桌面软件在linux系统上运行,开发起来还比较麻烦.微软只让c#的控 ...
- gcd|最大公约数|欧几里得算法|欧几里得算法证明 一文说明白
gcd 最大公因数,也称最大公约数.最大公因子,指两个或多个整数共有约数中最大的一个.a,b的最大公约数记为 $ gcd(a,b) $ ,同样的,a,b,c的最大公约数记为 $ gcd(a,b,c) ...
- 微信小程序文件预览和下载-文件系统
文件预览和下载 在下载之前,我们得先调用接口获取文件下载的url 然后通过wx.downloadFile将下载文件资源到本地 wx.downloadFile({ url: res.data.url, ...
- 从旺店通·企业奇门到用友U8通过接口集成数据
从旺店通·企业奇门到用友U8通过接口集成数据 接入系统:旺店通·企业奇门 慧策(原旺店通)是一家技术驱动型智能零售服务商,基于云计算PaaS.SaaS模式,以一体化智能零售解决方案,帮助零售企业数字化 ...
- EXCEL中逆向查找的十种方法
逆向查找在Excel中指的是根据某个数值或条件,查找该数值或条件所在的单元格位置.逆向查找可以帮助用户快速定位数据,对于数据分析和处理非常有用.下面将详细介绍在Excel中进行逆向查找的十种方法. 一 ...
- 机器学习-ROC曲线:技术解析与实战应用
本文全面探讨了ROC曲线(Receiver Operating Characteristic Curve)的重要性和应用,从其历史背景.数学基础到Python实现以及关键评价指标.文章旨在提供一个深刻 ...