页面切换后“蓝牙连接/数据丢失”的根因与遇到的其他问题的解决办法

一、问题背景

在 Flutter App 中集成 BLE 设备(如血氧仪)后,常见问题:

  • 页面切换(Get.to / Get.back)
  • 实际蓝牙 物理连接仍存在
  • 但 UI 显示:
    • 未连接
    • 数据归零
    • 波形停止
  • 需要重新连接才能恢复

二、根因总结(核心)

BLE 状态被绑定到了页面 / Controller 生命周期

当页面 pop 或 Controller dispose:

  • characteristic 被释放
  • notify 监听被 cancel
  • Rx 状态被重置

👉 导致 "逻辑断连",而不是"物理断连"


三、核心设计原则(务必牢记)

  • BLE = 全局资源
  • 页面 / Controller = 短生命周期
  • 任何 BLE 状态,都不能放在页面层

四、最终解决方案

架构分层

复制代码
BLE Service(单例 / 常驻)
├─ connect / disconnect
├─ characteristic / notify
├─ 数据解析
├─ StreamController.broadcast
├─ 连接状态快照
└─ 最新数据快照

Controller(页面级)
├─ 只维护 UI Rx 状态
├─ 订阅 Service Stream
└─ 从 Service 恢复快照

UI Page
└─ 纯展示(Obx)

五、关键实现要点

1️⃣ BLE Service 必须是单例

dart 复制代码
class BleService {
  static final BleService _instance = BleService._internal();
  factory BleService() => _instance;
  BleService._internal();
}

2️⃣ 所有 Stream 必须 broadcast

dart 复制代码
final StreamController<T> _ctrl =
    StreamController<T>.broadcast();

原因:

  • 多页面
  • 多 controller
  • 页面销毁不影响数据源

3️⃣ 连接状态 & 快照放在 Service

dart 复制代码
bool _connected;
String _deviceId;
String _deviceName;

Stream<bool> get connectionStream;
Pc60fOxiData? latestOxi;

4️⃣ Controller onInit 无感恢复

dart 复制代码
@override
void onInit() {
  connected.value = ble.isConnected;
  deviceName.value = ble.connectedDeviceName;

  final latest = ble.latestOxi;
  if (latest != null) {
    _onData(latest);
  }

  _connSub = ble.connectionStream.listen((v) {
    connected.value = v;
  });
}

5️⃣ 页面切换不影响 BLE

  • Controller 可销毁
  • Service 常驻
  • 页面回来 → 立刻恢复 UI

六、波形"贴底直线"的真实原因

  • 协议波形值:0 ~ 127
  • Controller 误归一化为:0 ~ 1
  • UI 按 0~127 绘制

👉 数值尺度不匹配

正确做法

dart 复制代码
waveformPoints.add(p.value.toDouble());

七、自动历史记录的节流策略

目标

  • 不高频写 Hive
  • 关键变化不丢

条件

  • 时间 ≥ 5 秒
  • 或 SpO₂ ≥ ±2%
  • 或 PR ≥ ±5 bpm

八、历史记录职责划分

方法 职责
_appendHistory_o 自动记录(后台、节流)
saveCurrentToHistory 用户手动保存
_saveRecord 统一写 Hive

九、总结

页面切换后数据丢失,不是 BLE 断了,
而是 BLE 状态放错了层级。

正确做法:
BLE 常驻,Controller 可销毁,UI 只展示。


十、BLE 项目模板骨架

📁 目录结构推荐

复制代码
lib/
└─ ble/
├─ ble_service.dart        // 单例,BLE 核心
├─ ble_models.dart         // 数据模型
├─ ble_parser.dart         // 协议解析
└─ ble_constants.dart

└─ feature_x/
├─ controller.dart         // UI Controller
├─ page_home.dart
├─ page_connect.dart
└─ page_history.dart

1️⃣ BLE Service 模板(核心)

dart 复制代码
class BleService {
  static final BleService _i = BleService._internal();
  factory BleService() => _i;
  BleService._internal();

  bool _connected = false;
  String _deviceId = '';
  String _deviceName = '';

  final StreamController<bool> _connCtrl =
      StreamController<bool>.broadcast();

  bool get isConnected => _connected;
  Stream<bool> get connectionStream => _connCtrl.stream;

  Future<void> connect(...) async {
    // connect + discover + notify
    _connected = true;
    _connCtrl.add(true);
  }

  Future<void> disconnect() async {
    _connected = false;
    _connCtrl.add(false);
  }
}

2️⃣ Controller 模板(UI 层)

dart 复制代码
class FeatureController extends GetxController {
  final ble = BleService();

  final connected = false.obs;
  StreamSubscription<bool>? _connSub;

  @override
  void onInit() {
    connected.value = ble.isConnected;

    _connSub = ble.connectionStream.listen((v) {
      connected.value = v;
    });
  }

  @override
  void onClose() {
    _connSub?.cancel();
    super.onClose();
  }
}

3️⃣ UI Page 模板

dart 复制代码
@override
Widget build(BuildContext context) {
  final c = Get.find<FeatureController>();

  return Obx(() {
    if (!c.connected.value) {
      return const Text('未连接');
    }
    return const Text('已连接');
  });
}

4️⃣ 永久避免问题的 Checklist

  • BLE Service 是否单例?
  • notify 是否只在 Service?
  • Stream 是否 broadcast?
  • Controller 是否只做 UI?
  • 是否有快照(latestData)?
  • 页面切换是否不影响 BLE?

✅ 这个模版解决的问题:

  • 页面随便切,BLE 不掉
  • Controller 随便销毁,状态不丢
  • UI 秒恢复
  • 波形 / 数据 / 历史稳定

相关推荐
MuMuMu12235 小时前
面向多场景碳普惠终端落地实践:越华环保集团碳惠小屋物联网终端架构分析
物联网·架构
笨笨饿8 小时前
#110_SCH3000 平台图传系统配置指南:从 DVP 摄像头到 UVC/WiFi 双通道传输
c语言·stm32·单片机·嵌入式硬件·物联网·vim
淡淡的香烟8 小时前
Android中的MQTT通信原理解析
android·物联网
笨笨饿10 小时前
#109_BK7258 蓝牙 A2DP 音频数据通路深度解析
python·stm32·单片机·mcu·物联网·编辑器·音视频
悟天特斯11 小时前
智慧楼宇边缘计算实战:从端侧自治到云边协同的算力下沉架构
人工智能·物联网·架构·边缘计算
数字新视界1 天前
动环监控系统为机房管理者带来了哪些好处?
物联网·数据中心·机房·动环监控系统·动力与环境监控系统·机房动环监控
一只鹿鹿鹿1 天前
大数据中心安全系统解决方案(Word文件)
大数据·运维·物联网·安全·政务
单片机杂货铺2 天前
【单片机毕业设计选题】基于单片机的智能牛奶保鲜箱设计
人工智能·stm32·单片机·物联网·毕业设计·课程设计
星恒讯工业路由器2 天前
新一代通信网:从“连接万物”到“智联万物”的关键跃迁
网络·物联网·智能路由器·工业路由器·工业物联网·5g-a·新一代通信网
数字化转型分享点滴2 天前
机加工车间上线 SH‑AIOT 物联网会遇到哪些常见实施难点
python·物联网