Flutter登录页跳转首页出现LateInitializationError问题求助
问题:Flutter页面跳转触发LateInitializationError
从登录页面跳转到首页时,出现以下错误:
═════════════ Exception caught by widgets library ═════════════ The following LateError was thrown building HomePage(dirty, dependencies: [_InheritedTheme, _LocalizationsScope-[GlobalKey#d5a11]], state: _HomePageState#10e51): LateInitializationError: Field 'items' has not been initialized. The relevant error-causing widget was HomePage lib\main.dart:22 When the exception was thrown, this was the stack #0 CatalogModel.items (package:flutter_catalog/models/catalog.dart) package:flutter_catalog/models/catalog.dart:1 #1 _HomePageState.build and so on.....
相关代码
catalog.dart
class CatalogModel { static late List<Item> items; // Get Item by ID Item getById(int id) => items.firstWhere((element) => element.id == id, orElse: null); // Get Item by position Item getByPosition(int pos) => items[pos]; } class Item { final int id; final String name; final String desc; final num price; int quantity; final String color; final String image; num get totalPrice => price * quantity; Item({ required this.id, required this.name, required this.desc, required this.price, required this.color, required this.image, this.quantity = 1, }); Item copyWith({ int? id, String? name, String? desc, num? price, String? color, int? quantity = 1, String? image, }) { return Item( id: id ?? this.id, name: name ?? this.name, desc: desc ?? this.desc, price: price ?? this.price, color: color ?? this.color, image: image ?? this.image, quantity: quantity ?? this.quantity, ); }
HomePage.dart
class HomePage extends StatefulWidget { @override _HomePageState createState() => _HomePageState(); } class _HomePageState extends State<HomePage> { @override void initState() { super.initState(); loadData(); } loadData() async { await Future.delayed(Duration(seconds: 2)); final catalogJson = await rootBundle.loadString("assets/files/catalog.json"); final decodedData = jsonDecode(catalogJson); var productsData = decodedData["products"]; CatalogModel.items = List.from(productsData) .map<Item>((item) => Item.fromMap(item)) .toList(); (VxState.store as MyStore).items = CatalogModel.items; setState(() {}); } @override Widget build(BuildContext context) { final _cart = (VxState.store as MyStore).cart; final MyStore store = VxState.store; return Scaffold( backgroundColor: context.canvasColor, floatingActionButton: VxBuilder( mutations: {AddMutation, RemoveMutation}, builder: (ctx,_,status) =>FloatingActionButton( onPressed: () => store.navigator.routeManager.push(Uri.parse(MyRoutes.cartRoute)), backgroundColor: context.theme.buttonColor, child: Icon( CupertinoIcons.cart, color: Colors.white, ), ).badge( color: Vx.red500, size: 22, count: _cart.items.length, textStyle: TextStyle( color: Colors.black, fontWeight: FontWeight.bold, )), ), body: SafeArea( child: Container( padding: Vx.m32, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ CatalogHeader(), CupertinoSearchTextField( onChanged: (value) { SearchMutation(value); }, ).py12(), if (CatalogModel.items !=null && CatalogModel.items.isNotEmpty) CatalogList().py16().expand() else CircularProgressIndicator().centered().expand(), ], ), ), )); } }
Cart.dart
class CartModel { late CatalogModel _catalog; final List<int> _itemIds = []; CatalogModel get catalog => _catalog; set catalog(CatalogModel newCatalog) { assert(newCatalog != null); _catalog = newCatalog; } List<Item> get items => _itemIds.map((id) => _catalog.getById(id)).toList(); num get totalPrice => items.fold(0, (total, current) => total + current.price); } class AddMutation extends VxMutation<MyStore> { final Item item; AddMutation(this.item); @override perform() { store!.cart._itemIds.add(item.id); } } class RemoveMutation extends VxMutation<MyStore> { final Item item; RemoveMutation(this.item); @override perform() { store!.cart._itemIds.remove(item.id); } }
解决方案
核心问题是**late修饰的静态变量items在异步初始化完成前被访问**,late变量未初始化时直接访问会触发LateInitializationError,而非返回null,导致build方法中的null判断失效。
1. 修改CatalogModel的items定义
将late改为可空类型,避免未初始化时访问报错:
class CatalogModel { // 改为可空列表,初始值为null static List<Item>? items; // 修改getById,处理items为null的情况,返回可空Item Item? getById(int id) => items?.firstWhere((element) => element.id == id, orElse: () => null); // 修改getByPosition,增加空判断和索引有效性检查 Item? getByPosition(int pos) { if (items == null || pos >= items!.length) return null; return items![pos]; } }
2. 修复CartModel的catalog初始化问题
将late CatalogModel改为可空类型,并在getter中增加空判断,避免访问未初始化的catalog:
class CartModel { CatalogModel? _catalog; final List<int> _itemIds = []; CatalogModel? get catalog => _catalog; set catalog(CatalogModel newCatalog) { _catalog = newCatalog; } // 修改items getter,过滤null值 List<Item> get items { if (_catalog == null || _catalog!.items == null) return []; return _itemIds.map((id) => _catalog!.getById(id)).whereType<Item>().toList(); } num get totalPrice => items.fold(0, (total, current) => total + current.price); }
3. 确保HomePage的逻辑兼容可空类型
原HomePage中的if (CatalogModel.items !=null && CatalogModel.items.isNotEmpty)判断已经兼容可空类型,无需修改。但要注意在CatalogList组件中,使用CatalogModel.items时要确保它不为null(因为判断已经过滤了null和空的情况)。
4. 保留required关键字
required是构造函数必填参数的修饰符,不能随意移除,否则会导致Item构造函数参数缺失的错误,保持原代码中的required即可。
完成以上修改后,从登录页跳转到首页时,build方法会先显示CircularProgressIndicator,直到loadData异步完成并初始化CatalogModel.items,之后自动切换显示CatalogList,不会再触发LateInitializationError。
内容的提问来源于stack exchange,提问作者Jayaditya Mishra
相关产品推荐
相关产品推荐

