Flutter中等待Future函数执行完毕后再执行后续代码问题求助
问题原因与解决方案
核心错误点
- 构造函数无法等待异步操作:Dart类的构造函数是同步执行的,不能标记为
async。你在ObjectService._internal()里调用Future.wait([initializeObject()]),只是发起了异步任务,但构造函数会直接返回实例,此时objectBox还未完成初始化。 - 未等待初始化完成就访问变量:调用单例时直接访问
myVariable,而late修饰的objectBox还没被赋值,触发未初始化错误。
修正后的单例类代码
重新设计单例的初始化逻辑,提供一个可等待的初始化方法,确保只执行一次:
import "package:flutter/cupertino.dart"; import '../repositories/objectbox_store.dart'; import "package:flutter/material.dart"; class ObjectService { late ObjectBox objectBox; static final ObjectService _instance = ObjectService._internal(); static Future<ObjectService>? _initializationTask; factory ObjectService() => _instance; ObjectService._internal(); // 全局初始化方法,确保只执行一次 static Future<ObjectService> init() async { if (_initializationTask == null) { _initializationTask = _instance._performInitialization(); } return _initializationTask!; } // 实际执行异步初始化的私有方法 Future<ObjectService> _performInitialization() async { WidgetsFlutterBinding.ensureInitialized(); objectBox = await ObjectBox.create(); return this; } ObjectBox get myVariable => objectBox; }
调用方代码修正
在页面中通过FutureBuilder等待初始化完成,再构建依赖ObjectBox的UI:
class ViewTransactionState extends State<ViewTransaction> { int count = 0; late Future<ObjectService> _serviceInitFuture; @override void initState() { super.initState(); // 提前触发单例初始化 _serviceInitFuture = ObjectService.init(); } @override Widget build(BuildContext context) { return Scaffold( floatingActionButton: FloatingActionButton( backgroundColor: colorPrimary, onPressed: () { Navigator.push(context, MaterialPageRoute(builder: (context) => const AddEditIncomeForm(addEditIndicator: 'Add'))); }, child: const Icon(Icons.add), ), body: FutureBuilder<ObjectService>( future: _serviceInitFuture, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { // 初始化中显示加载动画 return const Center(child: CircularProgressIndicator()); } else if (snapshot.hasError) { // 初始化失败显示错误信息 return Center(child: Text('初始化失败: ${snapshot.error}')); } else { // 初始化完成,构建数据流UI return _buildIncomeStream(snapshot.data!); } }, ), ); } Widget _buildIncomeStream(ObjectService service) { final stream = service.myVariable.store .box<Income>() .query() .watch(triggerImmediately: true) .map((query) => query.find()); return StreamBuilder<List<Income>>( stream: stream, builder: (context, streamSnapshot) { if (streamSnapshot.hasData) { // 根据实际业务展示数据列表 return ListView.builder( itemCount: streamSnapshot.data!.length, itemBuilder: (context, index) { final income = streamSnapshot.data![index]; return ListTile( title: Text(income.amount.toString()), // 补充其他字段展示 ); }, ); } else if (streamSnapshot.hasError) { return Center(child: Text('加载数据失败: ${streamSnapshot.error}')); } return const Center(child: CircularProgressIndicator()); }, ); } }
额外说明
WidgetsFlutterBinding.ensureInitialized()如果已经在main()函数中调用过(通常Flutter应用都会在main里先调用它),可以从_performInitialization中移除,避免重复调用。- 单例的
_initializationTask变量确保初始化逻辑只会执行一次,即使多次调用init()也不会重复创建ObjectBox实例。
内容的提问来源于stack exchange,提问作者yoohoo
相关产品推荐
相关产品推荐

