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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 08:39:57