如何在全局单例值变化时触发Flutter Widget重建
全局单例值变更触发组件重建实现方案
第一步:改造全局单例,值更新时发送通知
你当前的单例直接暴露了cartSize属性,外部修改值时无法触发通知,需要将属性改为私有,通过setter拦截赋值操作,值更新后自动调用notifyListeners()发出变更信号:
library #######.globals; import 'package:flutter/material.dart'; class GlobalSingleton extends ChangeNotifier { static final GlobalSingleton _instance = GlobalSingleton._internal(); factory GlobalSingleton() { return _instance; } GlobalSingleton._internal() { _cartSize = 0; } // 私有变量,禁止外部直接修改 late int _cartSize; // 提供getter供外部读取值 int get cartSize => _cartSize; // 提供setter,赋值时自动发通知 set cartSize(int value) { _cartSize = value; // 值变更后通知所有监听者 notifyListeners(); } }
注意:后续所有修改购物车数量的操作,都必须通过
GlobalSingleton().cartSize = 新值的方式赋值,才能触发通知,不要直接修改私有_cartSize变量。
第二步:在组件State中注册监听,收到通知触发重建
在购物车图标组件的状态类中,初始化时注册单例的变更监听,组件销毁时移除监听避免内存泄漏,收到通知后调用setState触发组件重建:
import 'package:######/globals/globals.dart'; import 'package:flutter/material.dart'; class BuildMarketplaceCartIcon extends StatefulWidget { const BuildMarketplaceCartIcon({Key? key}) : super(key: key); @override State<BuildMarketplaceCartIcon> createState() => _BuildMarketplaceCartIconState(); } class _BuildMarketplaceCartIconState extends State<BuildMarketplaceCartIcon> { CRUDMarketplaceCart localCartData = CRUDMarketplaceCart(); // 持有全局单例引用 final globalSingleton = GlobalSingleton(); @override void initState() { super.initState(); // 注册值变更监听 globalSingleton.addListener(_onCartSizeChange); } @override void dispose() { // 组件销毁时移除监听,防止内存泄漏 globalSingleton.removeListener(_onCartSizeChange); super.dispose(); } // 监听回调:收到通知时触发重建 void _onCartSizeChange() { if (mounted) { setState(() {}); } } @override Widget build(BuildContext context) { return InkWell( onTap: () { }, child: Container( width: 72, padding: const EdgeInsets.symmetric(horizontal: 8), child: Stack( alignment: Alignment.center, children: [ Column( mainAxisAlignment: MainAxisAlignment.center, children: const <Widget>[ Icon(Icons.shopping_cart), Text( 'Cart', overflow: TextOverflow.ellipsis, ), ], ), Positioned( top: 0, right: 0, child: Container( padding: const EdgeInsets.symmetric( horizontal: 6, vertical: 2, ), decoration: const BoxDecoration( shape: BoxShape.circle, color: Colors.white, ), alignment: Alignment.center, // 直接读取单例中的最新值 child: Text( '${globalSingleton.cartSize}', ), ), ), ], ), ), ); } }
使用说明
- 任何位置需要修改购物车数量时,直接执行
GlobalSingleton().cartSize = 新的数量即可,所有监听该值的组件会自动重建 - 回调中执行
setState前判断mounted是为了避免组件已经销毁时触发刷新报错
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

