You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中等待Future函数执行完毕后再执行后续代码问题求助

问题原因与解决方案

核心错误点

  1. 构造函数无法等待异步操作:Dart类的构造函数是同步执行的,不能标记为async。你在ObjectService._internal()里调用Future.wait([initializeObject()]),只是发起了异步任务,但构造函数会直接返回实例,此时objectBox还未完成初始化。
  2. 未等待初始化完成就访问变量:调用单例时直接访问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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 10:40:06