使用FlutterData的save()时出现model.key为空的空值检查异常
使用flutter_data包将API获取的数据本地存储时,调用remoteAdapter.save()触发Unhandled Exception: Null check operator used on a null value异常,异常出现在await localAdapter.save(model._key!, model)这一行的空值检查上。
相关代码实现如下:
遍历API返回结果调用save:
res.results.forEach((element) { element.save(element, remote: false); });
异常触发位置(flutter_data内部代码):
// ensure model is saved await localAdapter.save(model._key!, model); // 触发空值检查异常
自定义的PlaceAdapter:
mixin PlaceAdapter<T extends DataModelMixin<T>> on RemoteAdapter<T> { @override Future<T> save( model, { bool? remote, Map<String, dynamic>? params, Map<String, String>? headers, Object? onSuccess, Object? onError, DataRequestLabel? label, }) { return super.save(model, remote: false); } }
Place模型类:
@freezed @DataRepository([PlaceAdapter]) class Place with DataModelMixin<Place>, _$Place { Place._(); factory Place({ required String id, required String name, required String address, }) = _Place; factory Place.fromJson(Map<String, Object?> json) => _$PlaceFromJson(json); }
应用入口配置:
class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return ProviderScope( overrides: [ configureRepositoryLocalStorage( baseDirFn: () async => getApplicationDocumentsDirectory().then((dir) => dir.path), ), ], child: MaterialApp( debugShowCheckedModeBanner: false, navigatorKey: StackedService.navigatorKey, onGenerateRoute: StackedRouter().onGenerateRoute, home: Splashscreen(), ), ); } }
核心问题
异常根源是model._key为null,flutter_data内部用!空值检查导致崩溃。_key是框架为模型生成的本地存储标识,由框架自动管理,你的代码存在两处关键错误:
save方法调用传参错误
save是DataModelMixin的扩展方法,无需传入模型本身,你当前的调用element.save(element, remote: false)会导致框架无法正确识别实例,进而无法生成或关联_key。自定义Adapter泛型声明错误
PlaceAdapter的泛型写成T extends DataModelMixin<T>,但实际应绑定到具体的Place类型,错误泛型会导致框架处理模型元数据时异常,无法初始化_key。
修复步骤
- 修正save调用方式:
res.results.forEach((element) { element.save(remote: false); }); - 修正PlaceAdapter的泛型与参数类型:
mixin PlaceAdapter on RemoteAdapter<Place> { @override Future<Place> save( Place model, { bool? remote, Map<String, dynamic>? params, Map<String, String>? headers, Object? onSuccess, Object? onError, DataRequestLabel? label, }) { return super.save(model, remote: false); } } - (可选)如果API返回的主键字段不是
id,需在模型字段上添加@DataKey()注解指定主键,确保框架能正确关联模型标识。
额外说明
flutter_data的DataModelMixin会自动为模型实例注入_key,前提是实例通过框架规范方式创建(比如Place.fromJson解析、repository获取),不要手动修改_key相关内部字段。
内容的提问来源于stack exchange,提问作者Velliane

