Flutter应用收到Firebase推送时如何让AppBar操作按钮更新状态显示红点
实现方案
1. 修复现有代码的变量引用问题
你现有代码中Consumer的builder回调已经返回了最新的bloc实例,但小红点判断逻辑用的是类成员_bloc,属于引用了旧实例导致状态更新不生效,直接替换为回调返回的bloc即可:
@override Widget build(BuildContext context) { return Consumer<EventsBloc>(builder: (ctx, bloc, child) { return Container( child: AppBar( automaticallyImplyLeading: false, leading: widget.backButtonIcon != null ? widget.backButtonIcon : GestureDetector( child: Container( child: CanaryIcons().menu, padding: EdgeInsets.all(12), ), onTap: widget.onPressedLeading) ?? Container(), title: titleEmpty ? Container( padding: EdgeInsets.only(bottom: 20, top: 20), child: widget.title.isEmpty ? Text('Canary') : Text(widget.title), alignment: Alignment.center, ) : Text(widget.title, textAlign: TextAlign.center), actions: <Widget>[ GestureDetector( child: Container( padding: EdgeInsets.all(15), child: Stack(children: [ Icon(Icons.notifications_outlined), // 替换为回调返回的bloc实例,不要用旧的_bloc bloc.hasNotifications ?? false ? bloc.loadingState == ELoadingState.loading ? Container() : _redDot() : Container() ])), onTap: widget.onPressedAction) ], bottom: widget.bottom, elevation: 2, brightness: _brightness(), backgroundColor: CanaryColors.darkBlue, ), ); }); }
2. 配置Firebase前台消息监听
在应用根节点的initState中添加前台推送监听,收到推送时直接更新EventsBloc的状态:
@override void initState() { super.initState(); // 监听前台收到的Firebase推送 FirebaseMessaging.onMessage.listen((RemoteMessage message) { final eventsBloc = Provider.of<EventsBloc>(context, listen: false); // 更新未读通知状态 eventsBloc.updateUnreadStatus(true); }); }
3. 完善EventsBloc的状态通知逻辑
确保修改状态时调用了notifyListeners(),否则Provider不会触发UI刷新:
class EventsBloc extends ChangeNotifier { bool _hasNotifications = false; ELoadingState _loadingState = ELoadingState.idle; bool get hasNotifications => _hasNotifications; ELoadingState get loadingState => _loadingState; void updateUnreadStatus(bool hasUnread) { _hasNotifications = hasUnread; // 必须调用该方法通知所有监听组件刷新 notifyListeners(); } // 其余原有逻辑保持不变 }
可选优化:替换自定义红点为官方组件
可以直接用Flutter自带的Badge组件实现小红点,无需自己写_redDot方法,适配性更好:
Stack( children: [ Icon(Icons.notifications_outlined), if (bloc.hasNotifications == true && bloc.loadingState != ELoadingState.loading) Positioned( right: 0, top: 0, child: Badge( backgroundColor: Colors.red, smallSize: 8, ), ) ], )
内容的提问来源于stack exchange,提问作者ShwiftyMofo
相关产品推荐
相关产品推荐

