北京市建设公租房网站建什么网站可以赚钱

张小明 2026/1/2 0:00:02
北京市建设公租房网站,建什么网站可以赚钱,没有公网ip建设网站,动态页面怎么做欢迎大家加入[开源鸿蒙跨平台开发者社区](https://openharmonycrossplatform.csdn.net)#xff0c;一起共建开源鸿蒙跨平台生态。 在 Flutter 开发的迭代长河中#xff0c;状态管理始终是绕不开的核心命题。Provider 曾凭借简洁的 API 和低学习成本成为主流选择#xff0c;…欢迎大家加入[开源鸿蒙跨平台开发者社区](https://openharmonycrossplatform.csdn.net)一起共建开源鸿蒙跨平台生态。在 Flutter 开发的迭代长河中状态管理始终是绕不开的核心命题。Provider 曾凭借简洁的 API 和低学习成本成为主流选择但随着业务复杂度提升它的局限性逐渐暴露 —— 全局上下文依赖、类型安全不足、重构成本高、多状态组合繁琐等问题日益凸显。而 Riverpod 2.0 作为 Provider 的 “升级版”彻底解决了这些痛点同时保留了易用性还新增了缓存、自动刷新、多线程支持等高级特性。本文将从实际项目痛点出发手把手教你完成从 Provider 到 Riverpod 2.0 的无痛迁移同时解锁 Riverpod 的高性能玩法让状态管理既 “优雅” 又 “高效”。一、为什么要从 Provider 迁移到 Riverpod先通过一张表直观对比两者的核心差异理解迁移的价值特性ProviderRiverpod 2.0上下文依赖强依赖 BuildContext无上下文无法访问完全脱离 BuildContext随处可访问类型安全依赖Provider.ofT类型错误运行时才暴露编译期类型检查杜绝类型错误状态复用全局单例复用需手动封装支持局部 / 全局作用域复用更灵活重构成本改名 / 移位置需全局替换基于唯一标识符重构无感知缓存机制无原生缓存需手动实现内置缓存策略支持自动失效异步处理需结合 FutureProvider/StreamProviderAPI 繁琐AsyncNotifier 自动状态管理简化异步逻辑性能优化依赖 Consumer/Selector优化成本高细粒度重建控制默认高性能二、前置准备环境配置与核心概念1. 依赖引入在pubspec.yaml中添加 Riverpod 2.0 核心依赖yamldependencies: flutter: sdk: flutter flutter_riverpod: ^2.4.9 # 核心依赖包含Widget绑定 riverpod_annotation: ^2.3.1 # 注解支持可选简化代码 json_annotation: ^4.8.1 # 配合实体类序列化可选 dev_dependencies: flutter_test: sdk: flutter build_runner: ^2.4.6 # 注解生成代码 riverpod_generator: ^2.3.3 # Riverpod注解生成器 json_serializable: ^6.7.1 # 序列化代码生成器2. 核心概念速览Riverpod 2.0 的核心设计围绕 “提供者Provider” 和 “消费者Consumer” 展开且完全解耦上下文Provider状态的生产者分为Provider只读状态、StateProvider简单可变状态、NotifierProvider复杂状态、AsyncNotifierProvider异步状态等Ref状态的引用对象用于监听 / 更新其他 Provider、获取生命周期、缓存控制等ProviderScopeRiverpod 的根容器替代 Provider 的MultiProvider需包裹在 App 最外层Consumer/ConsumerWidget状态的消费者用于在 Widget 中监听状态变化。三、从 Provider 到 Riverpod 的分步迁移实战场景电商 App 的购物车状态管理我们以 “购物车添加 / 删除商品” 这个典型场景为例先展示 Provider 的实现方式再一步步迁移到 Riverpod 2.0并对比差异。步骤 1Provider 实现旧代码dart// 1. 定义购物车模型 class CartItem { final String id; final String name; final double price; int count; CartItem({ required this.id, required this.name, required this.price, this.count 1, }); } // 2. 定义Provider final cartProvider ChangeNotifierProvider((ref) CartProvider()); // 3. 实现ChangeNotifier class CartProvider extends ChangeNotifier { final ListCartItem _items []; ListCartItem get items _items; // 添加商品 void addItem(CartItem item) { final index _items.indexWhere((i) i.id item.id); if (index 0) { _items[index].count; } else { _items.add(item); } notifyListeners(); } // 删除商品 void removeItem(String id) { _items.removeWhere((item) item.id id); notifyListeners(); } // 计算总价 double get totalPrice { return _items.fold(0, (sum, item) sum item.price * item.count); } } // 4. Widget中使用 class CartPage extends StatelessWidget { override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text(购物车)), body: ConsumerCartProvider( builder: (context, cart, child) { if (cart.items.isEmpty) { return const Center(child: Text(购物车为空)); } return ListView.builder( itemCount: cart.items.length, itemBuilder: (context, index) { final item cart.items[index]; return ListTile( title: Text(item.name), subtitle: Text(¥${item.price} x ${item.count}), trailing: IconButton( icon: const Icon(Icons.delete, color: Colors.red), onPressed: () { cart.removeItem(item.id); }, ), ); }, ); }, ), floatingActionButton: FloatingActionButton( onPressed: () { // 添加商品依赖上下文 Provider.ofCartProvider(context, listen: false).addItem( CartItem( id: DateTime.now().microsecondsSinceEpoch.toString(), name: 新款T恤, price: 99.9, ), ); }, child: const Icon(Icons.add), ), ); } } // 5. 根Widget配置 void main() { runApp( ChangeNotifierProvider( create: (context) CartProvider(), child: const MyApp(), ), ); }步骤 2Riverpod 2.0 迁移新代码第一步重构根 Widget添加 ProviderScopedart// main.dart import package:flutter_riverpod/flutter_riverpod.dart; void main() { runApp( // 替代ChangeNotifierProvider包裹整个App const ProviderScope( child: MyApp(), ), ); } class MyApp extends StatelessWidget { const MyApp({super.key}); override Widget build(BuildContext context) { return MaterialApp( title: Riverpod购物车示例, home: const CartPage(), ); } }第二步用 Notifier 重构购物车状态核心dart// cart_notifier.dart import package:flutter_riverpod/flutter_riverpod.dart; // 1. 保持CartItem模型不变无需修改 class CartItem { final String id; final String name; final double price; int count; CartItem({ required this.id, required this.name, required this.price, this.count 1, }); } // 2. 定义Notifier替代ChangeNotifier class CartNotifier extends NotifierListCartItem { // 初始化状态替代构造函数 override ListCartItem build() { // 可在这里执行初始化逻辑如从本地缓存加载购物车 return []; } // 添加商品无notifyListeners状态更新自动通知 void addItem(CartItem item) { // 注意必须创建新列表不可变状态Riverpod通过引用对比检测变化 final newItems ListCartItem.from(state); final index newItems.indexWhere((i) i.id item.id); if (index 0) { // 同样创建新对象保证不可变性 newItems[index] CartItem( id: newItems[index].id, name: newItems[index].name, price: newItems[index].price, count: newItems[index].count 1, ); } else { newItems.add(item); } // 更新状态 state newItems; } // 删除商品 void removeItem(String id) { final newItems ListCartItem.from(state) ..removeWhere((item) item.id id); state newItems; } // 计算总价封装为计算属性也可抽离为单独Provider double get totalPrice { return state.fold(0, (sum, item) sum item.price * item.count); } } // 3. 定义Provider全局唯一无上下文依赖 final cartProvider NotifierProviderCartNotifier, ListCartItem(() { return CartNotifier(); }); // 4. 抽离总价为单独Provider细粒度控制重建 final cartTotalPriceProvider Providerdouble((ref) { // 监听购物车状态变化仅当状态改变时重新计算 final cartItems ref.watch(cartProvider); return cartItems.fold(0, (sum, item) sum item.price * item.count); });第三步重构 Widget脱离上下文依赖dart// cart_page.dart import package:flutter_riverpod/flutter_riverpod.dart; // 使用ConsumerWidget替代StatelessWidget自动关联Ref class CartPage extends ConsumerWidget { const CartPage({super.key}); override // 新增WidgetRef参数用于访问Provider Widget build(BuildContext context, WidgetRef ref) { // 监听购物车状态仅当列表变化时重建 final cartItems ref.watch(cartProvider); // 监听总价仅当总价变化时重建而非列表变化就重建 final totalPrice ref.watch(cartTotalPriceProvider); return Scaffold( appBar: AppBar( title: const Text(购物车), // 总价仅在变化时更新无需整个AppBar重建 actions: [ Padding( padding: const EdgeInsets.only(right: 16), child: Text(总价¥${totalPrice.toStringAsFixed(2)}), ) ], ), body: cartItems.isEmpty ? const Center(child: Text(购物车为空)) : ListView.builder( itemCount: cartItems.length, itemBuilder: (context, index) { final item cartItems[index]; return ListTile( title: Text(item.name), subtitle: Text(¥${item.price} x ${item.count}), trailing: IconButton( icon: const Icon(Icons.delete, color: Colors.red), onPressed: () { // 访问Notifier无上下文依赖 ref.read(cartProvider.notifier).removeItem(item.id); }, ), ); }, ), floatingActionButton: FloatingActionButton( onPressed: () { // 添加商品完全脱离上下文 ref.read(cartProvider.notifier).addItem( CartItem( id: DateTime.now().microsecondsSinceEpoch.toString(), name: 新款T恤, price: 99.9, ), ); }, child: const Icon(Icons.add), ), ); } }步骤 3关键差异解析状态不可变性Provider 中直接修改_items并调用notifyListeners()而 Riverpod 要求状态不可变 —— 必须创建新列表 / 新对象更新state这避免了隐式状态修改提升代码可维护性。上下文解耦Provider 的Provider.of/Consumer强依赖BuildContext而 Riverpod 通过WidgetRef访问状态可在任意位置如工具类、异步函数调用ref.read(cartProvider)无需上下文。细粒度重建将 “总价” 抽离为单独的cartTotalPriceProvider仅当总价变化时AppBar 的价格文本才重建而 Provider 中只要购物车列表变化整个 Consumer 包裹的区域都会重建。类型安全Riverpod 的ref.watch(cartProvider)编译期就确定返回ListCartItem而 Provider 的Provider.ofCartProvider若类型写错只有运行时才会报错。四、Riverpod 2.0 高级特性解锁高性能状态管理1. 异步状态管理AsyncNotifier在实际项目中购物车通常需要从网络 / 本地缓存加载Riverpod 的AsyncNotifier简化了异步状态处理dart// 1. 定义异步Notifier class AsyncCartNotifier extends AsyncNotifierListCartItem { // 模拟从本地缓存加载购物车 FutureListCartItem _loadCartFromLocal() async { await Future.delayed(const Duration(seconds: 1)); // 模拟耗时操作 // 实际项目中可从SharedPreferences/SQLite读取 return [ CartItem(id: 1, name: 默认商品, price: 59.9), ]; } override FutureListCartItem build() async { // 初始化时自动加载数据状态自动转为AsyncValue.loading/error/data return _loadCartFromLocal(); } // 添加商品并同步到本地 Futurevoid addItem(CartItem item) async { // 标记为加载中 state const AsyncValue.loading(); try { final currentItems state.value ?? []; final newItems ListCartItem.from(currentItems); final index newItems.indexWhere((i) i.id item.id); if (index 0) { newItems[index] CartItem( id: newItems[index].id, name: newItems[index].name, price: newItems[index].price, count: newItems[index].count 1, ); } else { newItems.add(item); } // 模拟同步到本地 await Future.delayed(const Duration(milliseconds: 500)); // 更新状态 state AsyncValue.data(newItems); } catch (e) { // 捕获异常状态自动转为error state AsyncValue.error(e, StackTrace.current); } } } // 2. 定义异步Provider final asyncCartProvider AsyncNotifierProviderAsyncCartNotifier, ListCartItem(() { return AsyncCartNotifier(); }); // 3. Widget中使用 class AsyncCartPage extends ConsumerWidget { const AsyncCartPage({super.key}); override Widget build(BuildContext context, WidgetRef ref) { // 监听异步状态自动处理loading/error/data final cartAsyncValue ref.watch(asyncCartProvider); return Scaffold( appBar: AppBar(title: const Text(异步购物车)), body: cartAsyncValue.when( loading: () const Center(child: CircularProgressIndicator()), error: (error, stack) Center(child: Text(加载失败$error)), data: (cartItems) { if (cartItems.isEmpty) { return const Center(child: Text(购物车为空)); } return ListView.builder( itemCount: cartItems.length, itemBuilder: (context, index) { final item cartItems[index]; return ListTile(title: Text(item.name)); }, ); }, ), ); } }2. 缓存与自动刷新Riverpod 支持缓存状态并可通过ref.refresh/ref.invalidate手动刷新或设置自动刷新dart// 定义带缓存的商品列表Provider final productListProvider FutureProviderListString((ref) async { // 设置缓存时间5秒5秒后自动失效刷新 ref.keepAliveFor(const Duration(seconds: 5)); // 模拟网络请求 await Future.delayed(const Duration(seconds: 1)); return [商品1, 商品2, 商品3]; }); // Widget中手动刷新 class ProductPage extends ConsumerWidget { const ProductPage({super.key}); override Widget build(BuildContext context, WidgetRef ref) { final productsAsync ref.watch(productListProvider); return Scaffold( appBar: AppBar(title: const Text(商品列表)), body: productsAsync.when( loading: () const Center(child: CircularProgressIndicator()), error: (e, s) Text(错误$e), data: (products) ListView.builder( itemCount: products.length, itemBuilder: (_, i) ListTile(title: Text(products[i])), ), ), floatingActionButton: FloatingActionButton( onPressed: () { // 手动刷新商品列表 ref.refresh(productListProvider); }, child: const Icon(Icons.refresh), ), ); } }3. 局部作用域避免全局状态污染Provider 的状态默认全局而 Riverpod 支持局部作用域比如为每个页面创建独立的购物车状态dartclass ScopedCartPage extends ConsumerWidget { const ScopedCartPage({super.key}); override Widget build(BuildContext context, WidgetRef ref) { return ProviderScope( // 覆盖全局cartProvider创建局部状态 overrides: [ cartProvider.overrideWith(() CartNotifier()), ], child: const CartPage(), // 复用之前的CartPage使用局部状态 ); } }五、迁移避坑指南1. 常见问题与解决方案问题原因解决方案状态更新后 Widget 不重建直接修改 state 对象未创建新对象确保状态不可变更新时创建新列表 / 新对象报错 “Provider not found”未添加 ProviderScope 根容器在 runApp 中包裹 ProviderScope上下文为空报错仍在使用 BuildContext 访问状态替换为 WidgetRef.read/watch性能反而下降过度使用 ref.watch导致频繁重建抽离细粒度 Provider使用 select 筛选状态2. 性能优化技巧使用 select 筛选状态仅监听需要的状态字段避免全量重建dart// 仅监听购物车商品数量而非整个列表 final itemCount ref.watch(cartProvider.select((items) items.length));延迟加载使用ref.watch(provider.notifier)仅获取通知器不监听状态避免在 build 中执行耗时操作将异步逻辑封装在 Notifier 的 build/addItem 中使用 keepAlive对高频访问的状态设置ref.keepAlive避免重复初始化。六、总结从 Provider 到 Riverpod 2.0 的迁移本质上是从 “命令式、上下文绑定、可变状态” 向 “声明式、上下文解耦、不可变状态” 的思维转变。Riverpod 2.0 不仅解决了 Provider 的核心痛点还通过异步状态管理、细粒度重建、缓存机制等特性大幅提升了状态管理的性能和可维护性。本文的迁移方案可直接落地到实际项目先替换根容器为ProviderScope逐步将ChangeNotifierProvider重构为NotifierProvider将 Widget 中的Consumer/Provider.of替换为ConsumerWidgetWidgetRef利用 Riverpod 的高级特性AsyncNotifier、缓存、局部作用域优化性能。相比于 ProviderRiverpod 2.0 的学习曲线稍高但一旦掌握会显著降低大型项目的状态管理复杂度。最后附上完整示例代码仓库示例https://github.com/xxx/flutter_riverpod_migration欢迎大家 Star、Fork也欢迎在评论区交流迁移过程中遇到的问题和优化思路
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

公司网站建设费入账软件开发网站模板

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 创建一个基于Python的僵尸游戏辅助脚本,功能包括自动瞄准、自动射击和资源收集。使用OpenCV进行图像识别来定位僵尸,PyAutoGUI模拟鼠标和键盘操作。要求脚本…

张小明 2026/1/1 0:58:27 网站建设

jsp网站模版长春企业免费建站

你是否曾经想过,如果有一个智能助手能够帮你处理GitHub上的各种操作,会是怎样的体验?想象一下,你只需用自然语言说"帮我查看最新的PR评论"或者"创建一个新的issue",AI就能立即执行这些任务。GitHu…

张小明 2026/1/1 18:49:50 网站建设

企业微网站哪个版本好济源专业做网站公司

在数字化转型的背景下,选择一款与业务契合的高品质私域电商系统,是企业构建自主数字渠道的关键决策。全球范围内的开源解决方案,凭借其灵活性、成本优势及成熟度,为不同规模的企业提供了稳健的技术基座。01 榜单揭晓:三…

张小明 2026/1/1 17:15:03 网站建设

如何做可以赚钱的网站张家港企业网站

量子电路的机器学习可靠性评估与排队论模型分析 1. 机器学习可靠性评估 在量子计算领域,对不同量子电路设计抽象层次下的机器学习(ML)可靠性评估是一个重要的研究方向。通过对提出的ML模型进行定性和定量比较,能够更深入地了解这些模型在量子计算中的有效性。 在实验中,…

张小明 2025/12/30 12:22:27 网站建设

广州网站优化排名哪家好androidstudio

Amlogic S9XXX Armbian刷机指南:让闲置电视盒子重获新生 【免费下载链接】amlogic-s9xxx-armbian amlogic-s9xxx-armbian: 该项目提供了为Amlogic、Rockchip和Allwinner盒子构建的Armbian系统镜像,支持多种设备,允许用户将安卓TV系统更换为功…

张小明 2026/1/1 12:05:31 网站建设

建设大型网站需要什么硬件外贸网站开发莆田

EmotiVoice 是否提供预训练模型?获取方式与技术实践全解析 在语音合成技术正从“能说”迈向“会表达”的今天,如何让机器声音具备情感、个性与真实感,已成为AI交互体验升级的关键命题。传统TTS系统虽然能准确朗读文本,但往往语调单…

张小明 2025/12/30 12:52:10 网站建设