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

Flutter中FutureBuilder无法进入ConnectionState.done状态求助

问题分析与解决方案

核心问题1:FutureBuilder的Future重复执行

你在build方法中直接将_logsService.getOrCreateUser(email: userEmail)作为FutureBuilder的future参数,而Flutter的build方法会被多次触发(比如屏幕旋转、父组件重建等),每次触发都会重新调用该方法创建新的Future,导致FutureBuilder永远无法进入ConnectionState.done状态,一直显示加载指示器。

解决方法:

在State类中定义一个Future变量,在initState中初始化它,避免重复执行:

class _LogsViewState extends State<LogsView> {
  late final LogsService _logsService;
  late final Future<DatabaseUser> _initUserFuture; // 新增变量
  String get userEmail => AuthService.firebase().currentUser!.email!;

  @override
  void initState(){
    _logsService = LogsService();
    _initUserFuture = _logsService.getOrCreateUser(email: userEmail); // 在这里初始化Future
    super.initState();
  }

  @override
  void dispose(){
    _logsService.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(backgroundColor: backgroundColour,
      appBar: AppBar(backgroundColor: backgroundColour,
        title:const Text("Your logs",
          style: TextStyle(color: Colors.white)         
        ),
 
      ),  
      body: FutureBuilder(
        future: _initUserFuture, // 使用预初始化的Future
        builder: (context, snapshot) {                
          switch (snapshot.connectionState) {
              case ConnectionState.done:
              return StreamBuilder(
                stream: _logsService.allLogs,
                builder: (context, snapshot) {                
                  switch (snapshot.connectionState) {
                    case ConnectionState.waiting:
                      return const Text('Waiting for all notes...');
                    default:
                      return const CircularProgressIndicator();
                  }
                },
              );
            default:
              return const CircularProgressIndicator();
          }
        },
      ),
      
    );
  }
}

核心问题2:LogsService的数据库连接未初始化

从你提供的LogsService代码来看,_db变量初始为null,但getUser和createUser方法大概率需要依赖这个数据库实例。如果没有初始化_db(比如打开数据库连接),getUser或createUser会因为缺少数据库连接而卡住,导致getOrCreateUser这个Future永远无法完成。

解决方法:

确保LogsService中初始化数据库连接,比如添加初始化方法并在调用getOrCreateUser前执行:

class LogsService {
  Database? _db;

  List<Databaselog> _logs = [];

  static final LogsService _shared = LogsService._sharedInstance();
  LogsService._sharedInstance();
  factory LogsService() => _shared;

  final _logsStreamController =
      StreamController<List<Databaselog>>.broadcast();

  Stream<List<Databaselog>> get allLogs => _logsStreamController.stream;

  // 新增数据库初始化方法
  Future<void> _initDatabase() async {
    if (_db != null) return;
    // 替换为你实际的数据库初始化逻辑(比如sqflite的openDatabase)
    _db = await openDatabase(
      'logs_database.db',
      version: 1,
      onCreate: (db, version) async {
        // 创建用户表、日志表等必要表结构
        await db.execute('''
          CREATE TABLE users(
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            email TEXT UNIQUE NOT NULL
          )
        ''');
      },
    );
  }

  Future<DatabaseUser> getOrCreateUser({required String email}) async {
    await _initDatabase(); // 先确保数据库已初始化
    try {
      final user = await getUser(email: email);
      debugPrint(user.toString());
      return user;
    } on CouldnotfindUser {
      final createdUser = await createUser(email: email);
      debugPrint(createdUser.toString());
      return createdUser;
    } catch (e) {
      debugPrint(e.toString());
      rethrow;
    }
  }
}

额外问题:StreamBuilder的状态处理逻辑缺陷

当前StreamBuilder仅处理ConnectionState.waiting状态,其余状态都返回加载指示器,但实际上当connectionState为active时,流可能已经推送了数据。应该结合snapshot.hasData、snapshot.hasError来完善逻辑:

StreamBuilder(
  stream: _logsService.allLogs,
  builder: (context, snapshot) {                
    if (snapshot.connectionState == ConnectionState.waiting) {
      return const Text('Waiting for all notes...');
    } else if (snapshot.hasError) {
      return const Text('Failed to load logs');
    } else if (!snapshot.hasData || snapshot.data!.isEmpty) {
      return const Text('No logs created yet');
    } else {
      // 替换为你的日志列表UI
      return ListView.builder(
        itemCount: snapshot.data!.length,
        itemBuilder: (context, index) {
          final log = snapshot.data![index];
          return ListTile(
            title: Text(log.title),
            subtitle: Text(log.content),
          );
        },
      );
    }
  },
)

内容的提问来源于stack exchange,提问作者Siddhartha Ravva

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 02:45:00