Provider

Provider是最基本的Provider组件,可以使用它为组件树中的任何位置提供值,但是当该值更改的时候,它并不会更新UI

class UserModel {String name = "kwok";void changeName() {name = "hello";}
}return Provider<UserModel>(create: (_) => UserModel(),child: MaterialApp(debugShowCheckedModeBanner: false,home: ProviderExample(),),
);import 'package:flutter/material.dart';
import 'package:flutter_provider_example/provider_example/user_model.dart';
import 'package:provider/provider.dart';class ProviderExample extends StatelessWidget {@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("ProviderExample"),),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [Consumer<UserModel>(builder: (_, userModel, child) {return Text(userModel.name,style: TextStyle(color: Colors.red,fontSize: 30));},),Consumer<UserModel>(builder: (_, userModel, child) {return Padding(padding: EdgeInsets.all(20),child: ElevatedButton(onPressed: (){userModel.changeName();},child: Text("改变值"),),);},),],),),);}
}

运行结果

我们点击按钮的会导致模型数据改变,但是模型数据改变之后UI并没有变化也没有重建,那是因为Provider提供者组件不会监听它提供的值的变化。

ChangeNotifierProvider

它跟Provider组件不同,ChangeNotifierProvider会监听模型对象的变化,而且当数据改变时,它也会重建Consumer(消费者),下面我们给出一个示例

import 'package:flutter/material.dart';class UserModel1 with ChangeNotifier {String name = "Kwok";void changeName() {name = "hello";notifyListeners();}
}
return ChangeNotifierProvider<UserModel1>(create: (_) => UserModel1(),child: MaterialApp(debugShowCheckedModeBanner: false,home: ChangeNotifierProviderExample(),),
);
import 'package:flutter/material.dart';
import 'package:flutter_provider_example/change_notifier_provider_example/user_model1.dart';
import 'package:provider/provider.dart';class ChangeNotifierProviderExample extends StatelessWidget {@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("ChangeNotifierProvider"),),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<UserModel1>(builder: (_, userModel, child) {return Padding(padding: EdgeInsets.all(20),child: ElevatedButton(onPressed: (){userModel.changeName();},child: Text("改变值"),),);},),],),),);}
}

FutureProvider

简单来说,FutureProvider用于提供在组件树中准备好使用其值时可能尚未准备好的值,主要是确保空值不会传递给任何子组件,而且FutureProvider有一个初始值,子组件可以使用该Future值并告诉子组件使用新的值来进行重建。

注意:

  • FutureProvider只会重建一次
  • 默认显示初始值
  • 然后显示Future
  • 最后不会再次重建
    第一步:创建模型
    这里和Provider不同的是增加了构造函数,以及changeName变成了Future,我们模拟网络请求延迟两秒后改变其值。class UserModel2{UserModel2({this.name});String? name = "Jimi";Future<void> changeName() async {await Future.delayed(Duration(milliseconds: 2000));name = "hello";}
    }
    第二步:提供Future
    我们有一个方法,就是异步获取userModel2,模拟网络请求延迟两秒执行,最后修改了name并返回UserModel2import 'package:flutter_provider_example/future_provider_example/user_model2.dart';class UserFuture {Future<UserModel2> asyncGetUserModel2() async {await Future.delayed(Duration(milliseconds: 2000));return UserModel2(name: "获取新的数据");}}
    第三步:应用程序入口设置
    initialData是默认值,create参数我们传了一个Future<UserModel2>,因为它接收的模型Create<Future<T>?>return FutureProvider<UserModel2>(initialData: UserModel2(name: "hello"),create: (_) => UserFuture().asyncGetUserModel2(),child: MaterialApp(debugShowCheckedModeBanner: false,home: FutureProviderExample(),),
    );
    第四步:使用共享数据
    import 'package:flutter/material.dart';
    import 'package:flutter_provider_example/future_provider_example/user_model2.dart';
    import 'package:provider/provider.dart';class FutureProviderExample extends StatelessWidget {@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("FutureProviderExample"),),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [Consumer<UserModel2>(builder: (_, userModel, child) {return Text(userModel.name ?? "",style: TextStyle(color: Colors.red,fontSize: 30));},),Consumer<UserModel2>(builder: (_, userModel, child) {return Padding(padding: EdgeInsets.all(20),child: ElevatedButton(onPressed: (){userModel.changeName();},child: Text("改变值"),),);},),],),),);}
    }
    

    StreamProvider

    StreamProvider提供流值,是围绕StreamBuilder,所提供的值会在传入的时候替换掉新值。和FutureProvider一样,主要的区别在于值会根据多次触发重新构建UI。

    第一步:创建模型

    class UserModel3{UserModel3({this.name});String? name = "kwok";void changeName() {name = "hello";}
    }
    

第二步:提供Stream

下面这段代码类似计时器,每隔一秒钟生成一个数字

import 'package:flutter_provider_example/stream_provider_example/user_model3.dart';class UserStream {Stream<UserModel3> getStreamUserModel() {return Stream<UserModel3>.periodic(Duration(milliseconds: 1000),(value) => UserModel3(name: "$value")).take(10);}
}
  • 第三步:应用程序入口设置

    这里也有initialData初始值,和FutureProvider类似,只是create属性是获取一个Stream流。

    return StreamProvider<UserModel3>(initialData: UserModel3(name: "hello"),create: (_) => UserStream().getStreamUserModel(),child: MaterialApp(debugShowCheckedModeBanner: false,home: StreamProviderExample(),),
    );

    第四步:使用共享数据

    import 'package:flutter/material.dart';
    import 'package:flutter_provider_example/stream_provider_example/user_model3.dart';
    import 'package:provider/provider.dart';class StreamProviderExample extends StatelessWidget {@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text("StreamProviderExample"),),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: [Consumer<UserModel3>(builder: (_, userModel, child) {return Text(userModel.name ?? "",style: TextStyle(color: Colors.red,fontSize: 30));},),Consumer<UserModel3>(builder: (_, userModel, child) {return Padding(padding: EdgeInsets.all(20),child: ElevatedButton(onPressed: (){userModel.changeName();},child: Text("改变值"),),);},),],),),);}
    }
    
  • MultiProvider

    在上面的例子中我们都只是返回了一个提供者,在实际开发过程中肯定会有多个提供者,我们虽然可以采用嵌套的方式来解决,但是这样无疑是混乱的,可读性级差。这个时候强大的MultiProvder就产生了,我们来看下示例:

    第一步:创建两个模型

    import 'package:flutter/material.dart';class UserModel1 with ChangeNotifier {String name = "kwok";void changeName() {name = "hello";notifyListeners();}
    }class UserModel4 with ChangeNotifier {String name = "kwok";int age = 18;void changeName() {name = "hello";age = 20;notifyListeners();}
    }
  • 第二步:应用程序入口设置

    相对于方式一这种嵌套方式设置,方式二就显得尤为简单。

    方式一:嵌套设置

    return ChangeNotifierProvider<UserModel1>(create: (_) => UserModel1(),child: ChangeNotifierProvider<UserModel4>(create: (_) => UserModel4(),child: MaterialApp(debugShowCheckedModeBanner: false,home: MultiProviderExample(),),),
    );
  • 方式二:使用MultiProvider

    return MultiProvider(providers: [ChangeNotifierProvider<UserModel1>(create: (_) => UserModel1()),ChangeNotifierProvider<UserModel4>(create: (_) => UserModel4()),/// 添加更多],child: MaterialApp(debugShowCheckedModeBanner: false,home: MultiProviderExample(),),
    );
    

    第三步:使用共享数据

    import 'package:flutter/material.dart';
    import 'package:flutter_provider_example/change_notifier_provider_example/user_model1.dart';
    import 'package:flutter_provider_example/multi_provider_example/user_model4.dart';
    import 'package:provider/provider.dart';class MultiProviderExample extends StatelessWidget {@overrideWidget 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("改变值"),),);},),],),),);}
    }
    

    ProxyProvider

    当我们有多个模型的时候,会有模型依赖另一个模型的情况,在这种情况下,我们可以使用ProxyProvider从另一个提供者获取值,然后将其注入到另一个提供者中。我们来看下代码演示

    第一步:创建两个模型

    下面我们创建了两个模型UserModel5WalletModel,而WalletModel依赖与UserModel5,当调用WalletModelchangeName方法时会改变UserModel5里面的name,当然我们在实际开发的过程中并不是这么简单,这里只是演示模型依赖时如果使用ProxyProvider

    import 'package:flutter/material.dart';class UserModel5 with ChangeNotifier {String name = "keo";void changeName({required String newName}) {name = newName;notifyListeners();}
    }class WalletModel {UserModel5? userModel5;WalletModel({this.userModel5});void changeName() {userModel5?.changeName(newName: "JIMI");}
    }
    

    第二步:应用程序入口设置

    return MultiProvider(providers: [ChangeNotifierProvider<UserModel5>(create: (_) => UserModel5()),ProxyProvider<UserModel5, WalletModel>(update: (_, userModel5, walletModel) => WalletModel(userModel5: userModel5),)],child: MaterialApp(debugShowCheckedModeBanner: false,home: ProxyProviderExample(),),
    );
    

    第三步:使用共享数据

    import 'package:flutter/material.dart';
    import 'package:flutter_provider_example/proxy_provider_example/user_model5.dart';
    import 'package:flutter_provider_example/proxy_provider_example/wallet_model.dart';
    import 'package:provider/provider.dart';class ProxyProviderExample extends StatelessWidget {@overrideWidget 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: 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("通过代理改变值"),),);},),],),),);}
    }
    

    ChangeNotifierProxyProvider

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

    下面我们给出一个例子:

  • 获取书籍列表
  • 获取收藏书籍列表
  • 点击书籍可加入或者取消收藏
  • 通过代理实时重构UI
  • 第一步:创建两个模型

    1、BookModel

    BookModel用户存储模型数据,将书籍转换成模型。

    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、BookManagerModel

    BookManagerModel主要用于管理书籍、收藏书籍、取消收藏等操作

    import 'package:flutter/material.dart';
    import 'package:flutter_provider_example/change_notifier_proxy_provider_example/models/book_model.dart';class BookManagerModel with ChangeNotifier {// 依赖bookModelfinal BookModel _bookModel;// 获取数据所有的IDList<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(),),
    );

    第三步:设置BottomNavigationBar

    import 'package:flutter/material.dart';
    import 'package:flutter_provider_example/change_notifier_proxy_provider_example/pages/page_a.dart';
    import 'package:flutter_provider_example/change_notifier_proxy_provider_example/pages/page_b.dart';class ChangeNotifierProxyProviderExample extends StatefulWidget {@override_ChangeNotifierProxyProviderExampleState createState() => _ChangeNotifierProxyProviderExampleState();
    }class _ChangeNotifierProxyProviderExampleState extends State<ChangeNotifierProxyProviderExample> {var _selectedIndex = 0;var _pages = [PageA(), PageB()];@overrideWidget 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: "收藏")],),);}
    }

    第四步:书籍列表UI构建

    import 'package:flutter/material.dart';
    import 'package:flutter_provider_example/change_notifier_proxy_provider_example/models/book_manager_model.dart';
    import 'package:flutter_provider_example/change_notifier_proxy_provider_example/models/book_model.dart';
    import 'package:flutter_provider_example/change_notifier_proxy_provider_example/widgets/book_item.dart';
    import 'package:provider/provider.dart';class PageA extends StatelessWidget {@overrideWidget 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),),);}
    }
  • 第五步:收藏列表UI构建

    import 'package:flutter/material.dart';
    import 'package:flutter_provider_example/change_notifier_proxy_provider_example/models/book_manager_model.dart';
    import 'package:flutter_provider_example/change_notifier_proxy_provider_example/widgets/book_item.dart';
    import 'package:provider/provider.dart';class PageB extends StatelessWidget {@overrideWidget 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),),);}
    }
    

    其他辅助封装类

    import 'package:flutter/material.dart';
    import 'package:flutter_provider_example/change_notifier_proxy_provider_example/models/book_manager_model.dart';
    import 'package:flutter_provider_example/change_notifier_proxy_provider_example/models/book_model.dart';
    import 'package:provider/provider.dart';class BookButton extends StatelessWidget {final Book book;BookButton({Key? key,required this.book}) : super(key: key);@overrideWidget 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),),);}
    }
    import 'package:flutter/material.dart';
    import 'package:flutter_provider_example/change_notifier_proxy_provider_example/models/book_model.dart';
    import 'package:flutter_provider_example/change_notifier_proxy_provider_example/widgets/book_button.dart';
    import 'package:provider/provider.dart';class BookItem extends StatelessWidget {final int id;BookItem({Key? key,required this.id}) : super(key: key);@overrideWidget 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),);}
    }

    总结

    Provider为我们提供了非常多的提供者,总共有八种。但我们比较常用的是ChangeNotifierProviderMultiProviderChangeNotifierProxyProvider,关于其他的提供者可根据自己的实际应用场景来。

Flutter Provider状态管理---八种提供者使用分析相关推荐

  1. Flutter Provider状态管理-Consumer

    前言 如果对Consumer很了解的同学可以继续学习 Flutter Provider状态管理 - Selector 个人觉得Flutter的学习有三个很重要的阶段 widget的学习和使用 数据以及 ...

  2. flutter基于provider状态管理设置主题颜色、实现简单登录、注册功能---页面+逻辑

    一.provider状态管理设置主题颜色 第一步: 安装依赖库 provider: ^4.3.2+3 第二步: 创建共享数据模型 import 'package:flutter/material.da ...

  3. Flutter GetX 状态管理 响应式编程(三)

    在码农的世界里,优美的应用体验,来源于程序员对细节的处理以及自我要求的境界,年轻人也是忙忙碌碌的码农中一员,每天.每周,都会留下一些脚印,就是这些创作的内容,有一种执着,就是不知为什么,如果你迷茫,不 ...

  4. Flutter GetX 状态管理 使用入门 程序计数器 (二)

    在码农的世界里,优美的应用体验,来源于程序员对细节的处理以及自我要求的境界,年轻人也是忙忙碌碌的码农中一员,每天.每周,都会留下一些脚印,就是这些创作的内容,有一种执着,就是不知为什么,如果你迷茫,不 ...

  5. Flutter - flutter_bloc状态管理

    继上一篇写了Flutter - GetX状态管理,会发现其实Flutter的状态管理的框架还是比较多的,用的比较多的有flutter_bloc.MobX.GetX等,今天我就来谈一谈我学习Flutte ...

  6. Flutter Provider 异步通信、Provider状态管理

    题记 -- 执剑天涯,从你的点滴积累开始,所及之处,必精益求精. Flutter是谷歌推出的最新的移动开发框架. [x1]微信公众号的每日提醒 随时随记 每日积累 随心而过 [x2]各种系列的视频教程 ...

  7. Provider状态管理练习

    一.添加依赖 provider: 6.0.5 二.创建CountModel.dart 注意:要继承ChangeNotifier import 'package:flutter/cupertino.da ...

  8. Flutter 对状态管理的认知与思考

    前言 关于这篇文章的一些内容,我很久之前就想写的,但一直没啥源动力,就一直鸽着 这次被捷特大佬催了几次,终于把这篇文章写完了,文章里有我对状态管理的一些思考和看法,希望能引起茫茫人海中零星的共鸣... ...

  9. Flutter _ 状态管理指南篇,Android开发两年

    ),); 然后我们开始测试,点击收藏按钮,查看 rebuild 情况. Performing hot reload- Syncing files to device iPhone Xs Max- - ...

最新文章

  1. Node.js 安装及环境配置之 Windows 篇
  2. Windows安装MRTG后的配置
  3. hdfs文档存储服务器,一文读懂HDFS分布式存储框架分析
  4. Spring与其他Web框架集成
  5. 惠普搜客户机t5740升级硬盘_惠普暗影精灵5首测重磅来袭:更多选择 更强性能...
  6. 变形金刚2_变形金刚(
  7. 基于.NET SingalR,LayIM2.0实现的web聊天室
  8. UVALive 7455 Linear Ecosystem (高斯消元)
  9. jquery中$.each循环的跳出
  10. 5G NR 链路自适应 Link Adaptation
  11. 首发Android 13!谷歌Pixel 7 Pro渲染图曝光:后置相机模组吸睛
  12. linux set命令例子,学习一个 Linux 命令:declare/typeset 命令
  13. [讲课视频]谈谈C/C++中的整数
  14. 微信小程序教程、微信小程序开发资源下载汇总(6.16日更新,持续更新中……)
  15. 苹果5越狱教程_unc0ver5.2.0安装方法 iOS13.5用Cydia Impactor或AltStore越狱教程
  16. mysql 左连接 左外连接吗_数据库左连接和左外连接有区别吗
  17. 超越宝典汽配汽修管理系统——“维修业务”模块功能实现
  18. JavaScript推箱子游戏开发笔记
  19. ubuntu 设置静态路由_Ubuntu添加静态路由
  20. jQuery WeUI v0.1.0 发布了 - 微信公众账号开发者的福音

热门文章

  1. 腾讯马松松谈企业安全建设:安全工程化如何落到实处
  2. geotools学习(七)地图样式
  3. 基于“总价、首付、贷款年限、利息、贷款额度”信息,计算每月最低还款额度。需要能按“等额本金、等额本息”两种形式计算还款
  4. 互联网热门职位薪资数据采集爬虫对比报告
  5. tp841虚拟服务器,TP-Link新版路由器虚拟服务器(端口映射)设置方法
  6. StarRocks斩获「2022 掘金引力榜」年度技术品牌传播案例 Top 10!
  7. 绩效考核六大认识误区解析(zt)
  8. python字符串的定界符不能是_Python|字符串str的构造、操作(操作符、函数、方法)...
  9. 2022-2028全球太阳能壁灯行业调研及趋势分析报告
  10. 2016 国庆,不庆