Flutter使用Hive添加收藏元素时调用null的routes属性报错如何解决?
问题根因
1. 报错直接触发原因
你在TransportService.getMarshrutWithStops方法的第75行List<Routes> routes = routesbyTransportType[ttId].routes;中,routesbyTransportType[ttId]返回了null,直接调用null对象的routes属性触发了NoSuchMethodError。
2. 收藏逻辑核心错误
你的Hive操作key不匹配:
- 保存收藏时,你用列表下标
index作为Hive的key存储数据:favoriteRoutesBox.put(index, _routes[index]); - 删除收藏时,你用业务id
_routes[index].route.ttId作为key删除:favoriteRoutesBox.delete(_routes[index].route.ttId);
两者完全不对应,导致你点击取消收藏时根本删不掉对应存储的条目,甚至可能误删其他数据。删除操作完成后你也没有调用setState刷新UI状态,页面状态和Hive存储状态不一致,重新进入收藏页时传入的widget.ttId可能已经是无效值,导致routesbyTransportType中找不到对应key的条目,触发空异常。
3. 缺少防御性校验
getMarshrutWithStops方法没有对routesbyTransportType[ttId]做非空判断,就算fetchTransportWithRoutes执行完成,也无法保证routesbyTransportType中一定存在入参ttId对应的条目。
修复方案
1. 修复Service层空校验
修改getMarshrutWithStops方法,增加非空判断:
Future<List<RouteWithStops>> getMarshrutWithStops(int ttId) async { if (routesbyTransportType.isEmpty) { await fetchTransportWithRoutes(); } // 增加非空判断 final transportItem = routesbyTransportType[ttId]; if (transportItem == null || transportItem.routes == null) { return []; } List<Routes> routes = transportItem.routes; List<ScheduleVariants> variants = []; variants.addAll(await api.fetchSchedule()); List<RouteWithStops> routesWithStops = []; for (Routes route in routes) { final routeWithStops = RouteWithStops(); // 匹配到对应的调度变体再添加,避免取不到值报错 final matchedVariant = variants.where((variant) => variant.mrId == route.mrId).firstOrNull; if (matchedVariant != null) { routeWithStops.route = route; routeWithStops.variant = matchedVariant; routesWithStops.add(routeWithStops); } } return routesWithStops; }
2. 统一Hive操作的key,修复收藏逻辑
推荐用业务唯一id作为Hive的key,避免列表顺序变化导致key错位,同时删除后刷新UI:
Widget getIcon(int index) { // 用业务id判断是否存在收藏 final routeId = _routes[index].route.ttId; if (favoriteRoutesBox.containsKey(routeId)) { return Icon(Icons.favorite, color: Colors.red); } return Icon(Icons.favorite_border); } void onFavoritePress(int index) { final routeId = _routes[index].route.ttId; if (favoriteRoutesBox.containsKey(routeId)) { favoriteRoutesBox.delete(routeId); } else { favoriteRoutesBox.put(routeId, _routes[index]); } // 刷新UI状态 setState(() {}); }
3. 增加异步调用异常捕获
修改页面initState,对异步请求增加异常捕获,避免未处理异常直接崩溃:
@override void initState() { super.initState(); // 先初始化Hive和控制器 favoriteRoutesBox = Hive.box(favoritesBox); _editingController = TextEditingController(); // 确保ttId是有效值再发起请求 if (widget.ttId != null) { service.getMarshrutWithStops(widget.ttId).then((value) { if (mounted) { setState(() { _routes.addAll(value); }); } }).catchError((err) { // 按需处理异常,比如弹出提示 debugPrint('加载路线失败: $err'); }); } }
内容的提问来源于stack exchange,提问作者user16357470
相关产品推荐
相关产品推荐

