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
相关产品推荐
相关产品推荐

