Flutter应用初始化提示getter 'menuBadge' was called on null错误如何解决
报错根因
应用初始化阶段,Firestore的Stream异步请求还未完成返回数据,此时allBadges列表为空,showFeedbadge getter会返回null,你直接对返回值调用.menuBadge就触发了空指针异常。后续Stream拿到数据后刷新UI,所以功能看起来正常,但初始化阶段的报错需要处理。
可行解决方案
方案1:使用Dart空安全调用符处理空值(改动最小)
直接在调用menuBadge的地方用空安全语法,同时给默认值即可:
badge = badgeManager.showFeedbadge?.menuBadge ?? false;
?.会在前面的对象为null时直接返回null,??操作符会在左侧值为null时返回右侧的默认值,这里默认不显示角标就设为false。
方案2:优化getter逻辑,默认返回非空Badge对象
修改showFeedbadge getter,找不到对应用户的Badge时,返回一个默认menuBadge为false的对象,避免返回null:
Badge get showFeedbadge { for (int i = 0; i < allBadges.length; i++) { if (allBadges.elementAt(i).userId == authUser.id) { print(allBadges.elementAt(i).menuBadge); return allBadges.elementAt(i); } } // 找不到时返回默认对象,不返回null return Badge(menuBadge: false, userId: authUser.id); }
方案3:增加加载状态判断,初始化阶段先展示无角标图标
在BadgeManager里加一个isLoading的状态变量,Stream拿到第一次数据前设为true,拿到后设为false,UI层根据状态判断展示逻辑:
// BadgeManager里新增变量 bool isLoading = true; void _listenToBadges() { _subscription = activityFeedref .where('userId', isEqualTo: authUser.id) .snapshots() .listen((event) { allBadges.clear(); for (final doc in event.docs) { allBadges.add(Badge.fromDocument(doc)); } // 第一次拿到数据后修改加载状态 if (isLoading) isLoading = false; if (!isDisposed) { notifyListeners(); } }); }
UI层同步修改:
builder: (BuildContext context) { // 注意这里要用watch而不是read,才能监听状态变化刷新UI final badgeManager = context.watch<BadgeManager>(); final badge = badgeManager.isLoading ? false : badgeManager.showFeedbadge.menuBadge; return IconButton( icon: BadgeIcon(show: badge, icon: Icon(Icons.menu)), onPressed: () { Scaffold.of(context).openDrawer(); }, ); }
额外优化建议
你现在的Stream查询已经过滤了userId等于当前用户ID的文档,所以返回的结果里所有Badge的userId都是当前用户,showFeedbadge里的循环判断其实是冗余的,可以直接简化为:
Badge get showFeedbadge { if (allBadges.isNotEmpty) return allBadges.first; return Badge(menuBadge: false, userId: authUser.id); }
内容的提问来源于stack exchange,提问作者Ricardo Oscar Kanitz
相关产品推荐
相关产品推荐

