Flutter问题:SqlConn.isConnected变量为何无法正确更新?
热重启后SqlConn.isConnected显示false但仍能查询数据库的原因及解决办法
问题场景
我使用sql_conn包实现数据库连接,通过SqlConn.isConnected的值判断用户是否可继续使用应用——当该值为false时跳转至登录界面。
正常启动应用时,SqlConn.isConnected初始值为false,点击Connect按钮可正常建立连接,点击Read按钮也能成功返回数据。但热重启后,SqlConn.isConnected显示为false,点击Read按钮却依然能查询到数据库数据,出现状态与实际行为不符的问题。
问题代码
import 'package:ats/providers/globals_provider.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:sql_conn/sql_conn.dart'; class Login extends StatefulWidget { const Login({super.key}); @override State<Login> createState() => _LoginState(); } class _LoginState extends State<Login> { final globals = GlobalsProvider(); Future<void> connect(BuildContext ctx) async { debugPrint("Connecting..."); try { showDialog( context: context, builder: (context) { return const AlertDialog( title: Text("LOADING"), content: CircularProgressIndicator(), ); }, ); await SqlConn.connect( ip: "ipAddress", port: "1433", databaseName: "DB", username: "sa", password: "password"); debugPrint("Connected!"); updateConnectionStatus(); } catch (e) { debugPrint(e.toString()); updateConnectionStatus(); } finally { Navigator.pop(context); } } Future<void> read(String query) async { var res = await SqlConn.readData(query); debugPrint(res.toString()); } Future<void> write(String query) async { var res = await SqlConn.writeData(query); debugPrint(res.toString()); } Future<void> disconnect() async { SqlConn.disconnect(); updateConnectionStatus(); } void updateConnectionStatus() { globals.connected = SqlConn.isConnected; setState(() {}); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Login'), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ ElevatedButton( onPressed: () { if (kDebugMode) { print('${globals.debugATS} globals.connected: ${globals.connected.toString()}'); print('${globals.debugATS} SqlConn.isConnected: ${SqlConn.isConnected.toString()}'); } }, child: const Text('Check connection status') ), Text('globals.connected: ${globals.connected.toString()}'), Text('SqlConn.isConnected: ${SqlConn.isConnected.toString()}'), ElevatedButton( onPressed: () => connect(context), child: const Text("Connect")), ElevatedButton( onPressed: () => read("SELECT * FROM EMPLOYEE"), child: const Text("Read")), ElevatedButton( onPressed: () => disconnect(), child: const Text("Disconnect")) ], ), )); } }
原因分析
这是sql_conn包的状态维护机制导致的:
SqlConn.isConnected是Dart层维护的内存状态变量,热重启时Flutter的Dart虚拟机会重启,所有Dart层的内存变量都会重置为初始值(即false)。- 但原生平台(Android/iOS)侧的数据库连接并没有被销毁,依然保持活跃状态。当调用
readData时,原生侧会直接使用已存在的连接执行查询,导致Dart层的状态显示与实际连接情况不符。
解决办法
1. 启动时主动校验连接状态
在页面初始化时,执行一个轻量的测试查询(比如SELECT 1),根据查询结果同步Dart层的连接状态:
@override void initState() { super.initState(); _syncConnectionStatus(); } Future<void> _syncConnectionStatus() async { try { // 执行轻量查询测试连接有效性 await SqlConn.readData("SELECT 1"); // 如果查询成功,说明连接仍有效,更新状态 if (globals.connected != true) { globals.connected = true; setState(() {}); } } catch (e) { // 查询失败,说明连接已断开,保持状态为false if (globals.connected != false) { globals.connected = false; setState(() {}); } } }
2. 封装独立的连接状态管理
不要直接依赖SqlConn.isConnected,自己实现全局的连接状态管理:
- 调用
connect成功后,手动标记状态为true - 调用
disconnect后,标记状态为false - 每次应用启动(包括热重启),通过测试查询同步状态
3. 监听应用生命周期
在应用从后台恢复或热重启后,触发连接状态校验,确保Dart层状态与原生侧一致。可以使用WidgetsBindingObserver监听生命周期事件:
@override void didChangeAppLifecycleState(AppLifecycleState state) { super.didChangeAppLifecycleState(state); // 应用从后台回到前台时,重新校验连接状态 if (state == AppLifecycleState.resumed) { _syncConnectionStatus(); } }
内容的提问来源于stack exchange,提问作者TheMortiestMorty
相关产品推荐
相关产品推荐

