4. GATT与依赖注入的相遇场景:BLE设备驱动与业务逻辑解耦需求

在嵌入式BLE系统中,GATT协议栈通常由芯片厂商的SDK或操作系统层提供固定实现。传统做法是业务逻辑直接调用GATT API,导致驱动代码与业务场景高度耦合。本章聚焦于依赖注入(DI)介入GATT读写事件的典型场景——当BLE设备驱动需要与上层业务逻辑解耦时,DI成为控制反转的关键边界。

4.1 场景边界:谁依赖谁,谁控制谁

解耦需求的核心在于依赖关系的方向。业务逻辑不应该直接构造或持有GATT驱动实例,而应通过DI容器接收抽象的GattService接口。边界定义如下:

边界侧所属层典型组件依赖方向
GATT驱动硬件抽象层(HAL)GattCallback、NotificationHandler被DI容器管理
服务接口抽象层IGattCharacteristic、IGattReadCallback无依赖
业务逻辑应用层DeviceMonitor、DataProcessor消费接口,不依赖具体实现
DI容器基础设施层DaggerComponent、ManualInjector装配依赖,控制实例生命周期

4.2 分层与组件职责

为了实现上述边界,系统被划分为四个清晰层级,每一层只暴露并依赖接口,不引用具体类。

  • GATT协议适配层:封装系统级BLE API,注册回调,完成MTU协商、通知启停、读写操作。本层不处理业务数据含义。
  • 服务抽象层:定义 IGattCharacteristic、INotificationReceiver 等接口。接口参数与返回值均为纯业务结构体,不暴露GATT句柄或UUID。
  • 业务逻辑层:通过构造函数接收接口实例,消费特征值变化、发起读写请求。不再调用任何系统BLE API。
  • DI装配层:负责将GATT驱动实现注入到业务层。注入时机通常发生在设备连接成功后、业务启动前。
设计提示:服务抽象层是整个解耦方案的锚点。接口中不应出现 BluetoothGattCharacteristic、BluetoothGattDescriptor 等平台类型,而应使用自定义数据类型或通用字节流。

4.3 数据流、控制流与信任链路

下图展示了从BLE硬件事件到达后,经过DI边界到达业务逻辑的完整链路:

GATT与DI整合架构数据流 BLE硬件 GATT驱动层 IGattService接口 DI容器 业务逻辑 实例生命周期 控制反转: 业务不持有驱动

数据流可以概括为三个步骤:

  1. GATT事件产生:BLE硬件发出通知或读响应,GATT驱动层收到原始数据。
  2. 接口回调:驱动层将数据包装为业务友好的格式,回调 IGattService 方法。
  3. 业务消费:业务逻辑层通过DI得到的接口实例接收数据,完成处理、存储或UI更新。

控制流的关键在于DI容器介入时间——在设备连接建立后、业务层启动前完成注入,避免驱动实例在业务层生命周期内被意外替换。

4.4 选型权衡:手动注入 vs 框架注入

在嵌入式BLE场景下,资源受限,DI选型是一个重要权衡点。下表对比两种常见方案:

维度手动依赖注入框架注入(Dagger / Hilt)
启动开销近乎为零反射/APT编译期生成,运行时少量开销
代码量需显式编写工厂类注解驱动,自动生成
调试难度低,调用链可见中等,需要理解作用域和组件树
生命周期管理需手动绑定连接和断开通过 @ActivityScoped 或 @ServiceScoped 自动管理
推荐场景RAM < 256KB、无Java虚拟机Android类系统、支持KSP/APT
风险警示:在低端MCU上使用框架注入可能导致Flash占用大幅增加(约40-80KB),且初始化时间不可预测。建议资源紧缺的嵌入式环境优先选择手动注入。

4.5 风险点与应对措施

  • 生命周期不匹配:BLE连接断开后,DI容器仍然持有驱动实例,导致悬挂引用。应在 onDisconnected 中清理或重置作用域。
  • 线程安全问题:GATT回调可能在不同线程执行,DI注入的实例需要保证线程安全或使用不可变对象。
  • 接口膨胀:每个服务都需要单独接口,导致接口数量激增。采用泛型接口(如 IGattCharacteristic<T>)可缓解。

4.6 落地步骤与验收标准

步骤操作预期产物
Step 1定义业务所需的GATT服务接口集IGattReadService、IGattNotificationService
Step 2实现驱动适配层,适配系统BLE回调GattAccessor 类
Step 3搭建DI容器(手动工厂或框架组件)GattComponentFactory
Step 4在设备连接后触发注入injectGattDependencies(connectionId)
Step 5编写测试,模拟接口替代真实驱动Mock对象+DI容器测试
验收标准:
  • 业务层代码不引用任何 BluetoothGatt、GattCallback 或 BluetoothDevice。
  • 断开连接后,DI容器不持有已断开的驱动实例引用。
  • 更换GATT驱动实现时(如从系统BLE切换为自定义HCI层),无需修改业务逻辑层任何代码。
  • 单元测试中可传递任何符合接口定义的模拟对象,无运行时异常。