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

一、问题背景

在 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 秒恢复
  • 波形 / 数据 / 历史稳定

相关推荐
物联网IoT小易13 分钟前
物联网设备数据异常怎么处理?重复、乱序、断点续传与脏数据治理
物联网·mqtt·数据治理·时序数据库·物联网设备·物联网设备接入·物联网设备连接
航飞光电市场经理37 分钟前
【工业物联网】UWB/北斗/蓝牙多源融合定位技术对比:主流厂商技术路线解析
物联网
桐盛科技4 小时前
能碳数据清洗用MAD算法,窗口大小和阈值怎么调?
物联网·算法·边缘计算
wuyk5558 小时前
【Socket 进阶之路】第 3 章 TCP 三次握手 & 四次挥手深度剖析|连接建立、断开、状态机、TIME_WAIT 核心工程问题
服务器·开发语言·网络·物联网·网络协议·tcp/ip
超智算科技18 小时前
2026服贸会现场直击|Net Zero Hub净零算力枢纽全球首发! 超智算受邀深度参与服贸会全球OPC共创节
网络·人工智能·科技·物联网·gpu算力
数字新视界20 小时前
动环监控系统技术深度剖析与应用探索
物联网·动环监控·机房·机房动环监控系统·动力与环境监控系统
Privasa-隐私实验室21 小时前
蓝牙-多设备调试效率翻倍:从手动折腾到全自动调试的完整落地流程
物联网·ios·智能家居·智能硬件·智能手表
悟天特斯1 天前
AI驱动的楼宇节能:从粗放管控到精准降碳的实践路径
开发语言·人工智能·python·物联网
沐欣工作室_lvyiyi1 天前
基于物联网技术的农业气象数据采集与分析平台(论文+源码)
物联网·毕业设计·软件工程·单片机设计·4g通信·电子信息工程·物联网毕业设计
MuMuMu12231 天前
再生资源回收终端物联网落地实践,越华环保集团碳惠小屋边缘数据方案解析
物联网