Flutter Web调试模式下Freezed自定义模型fromJson调用失败
问题描述
在Flutter Web项目中定义了如下Freezed自定义模型:
@freezed class User with _$User { const factory User({ required int id, required String name, required Address address, @Default(null) Contact? contact, }) = _User; factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json); }
Address、Coordinates及Contact模型定义如下:
@Freezed() class Address with _$Address { const factory Address({ required String type, required String address, required String subDistrict, required String district, required String state, required String country, required String pincode, Coordinates? coordinates, }) = _Address; factory Address.fromJson(Map<String, dynamic> json) => _$AddressFromJson(json); } @Freezed() class Coordinates with _$Coordinates { const factory Coordinates({ required double latitude, required double longitude, }) = _Coordinates; factory Coordinates.fromJson(Map<String, dynamic> json) => _$CoordinatesFromJson(json); }
@Freezed() class Contact with _$Contact { const factory Contact({ @Default([]) List<String> email, @Default([]) List<String> mobile, @Default([]) List<String> landline, @Default([]) List<String> fax, }) = _Contact; factory Contact.fromJson(Map<String, dynamic> json) => _$ContactFromJson(json); }
调用User.fromJson从JSON创建实例时,抛出错误:
NoSuchMethodError: tried to call a non-function, such as null: 'user$.User.fromJson'
问题细节:
- 仅User模型出现该问题,移除
@Default(null)后问题依旧 - 已确认传入的是Map类型而非字符串
- 仅调试模式触发,发布模式运行正常
环境及依赖版本:
Flutter 3.7.9 • channel stable • https://github.com/flutter/flutter.git Framework • revision 62bd79521d (2 weeks ago) • 2023-03-30 10:59:36 -0700 Engine • revision ec975089ac Tools • Dart 2.19.6 • DevTools 2.20.1 dependencies: freezed_annotation: ^2.2.0 json_annotation: ^4.8.0 dev_dependencies: build_runner: ^2.3.3 freezed: ^2.3.2 json_serializable: ^6.6.1
堆栈追踪:
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 45:50 <fn> C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/zone.dart 1660:54 runUnary C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/future_impl.dart 147:18 handleValue C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/future_impl.dart 767:44 handleValueCallback C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/future_impl.dart 796:13 _propagateToListeners C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/future_impl.dart 567:5 [_completeWithValue] C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/future_impl.dart 640:7 callback C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/schedule_microtask.dart 40:11 _microtaskLoop C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/schedule_microtask.dart 49:5 _startMicrotaskLoop C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 166:15 <fn>
原因分析及解决方案
这个问题是Flutter Web调试模式下的代码生成延迟/未正确加载导致的。调试模式采用JIT编译,Freezed生成的_$UserFromJson方法没有被提前初始化加载,调用时就会出现null无法执行的错误;而发布模式是AOT编译,所有代码(包括生成代码)都会被提前打包,因此不会出现这个问题。
具体解决步骤:
强制预加载生成代码
在调用User.fromJson之前,提前触发生成代码的加载,比如在初始化代码里添加:// 引用生成文件中的方法,触发加载 import 'user.g.dart' as user_gen; void init() { // 仅触发加载,无需实际调用 user_gen._$UserFromJson; }或者直接创建一个空的
_$User实例:_$User(const User(id: 0, name: '', address: Address(type: '', address: '', subDistrict: '', district: '', state: '', country: '', pincode: '')));彻底清理并重新生成代码
执行以下命令,清除旧的生成文件并重新构建:flutter clean flutter pub get flutter pub run build_runner build --delete-conflicting-outputs检查导入与代码结构
确保所有模型的.g.dart生成文件都被正确导入,且没有循环导入的情况。禁用Web延迟加载
如果以上方法无效,可在pubspec.yaml中关闭Flutter Web的延迟加载:flutter: web: defer_js: false
内容的提问来源于stack exchange,提问作者Damien Leon
相关产品推荐
相关产品推荐

