Flutter中用Hive存储flutter_blue嵌套对象报错求助
解决Hive存储flutter_blue类的序列化错误
你遇到的问题核心是:Hive无法直接序列化flutter_blue库中的BluetoothDevice、BluetoothService、BluetoothCharacteristic类,这些类既不是Hive内置支持的类型,也没有实现Hive的序列化适配。下面提供两种可行的解决方案,更推荐第二种,因为稳定性更高。
方案一:为flutter_blue类自定义Hive TypeAdapter
你需要为每个flutter_blue的目标类编写对应的适配器,注册后Hive就能识别并序列化它们。
1. 编写BluetoothDevice适配器
创建bluetooth_device_adapter.dart:
import 'package:flutter_blue/flutter_blue.dart'; import 'package:hive/hive.dart'; class BluetoothDeviceAdapter extends TypeAdapter<BluetoothDevice> { @override final typeId = 1; // 确保该ID与其他Hive类型ID不重复(比如你的SavedDevice是0) @override BluetoothDevice read(BinaryReader reader) { // 读取存储的设备标识,反序列化为BluetoothDevice实例 final deviceIdStr = reader.readString(); return BluetoothDevice.fromId(DeviceIdentifier(deviceIdStr)); } @override void write(BinaryWriter writer, BluetoothDevice obj) { // 只存储设备的唯一标识和名称(必要字段) writer.writeString(obj.id.toString()); writer.writeString(obj.name ?? 'Unknown Device'); } }
2. 编写BluetoothService和BluetoothCharacteristic适配器
类似地,为这两个类编写适配器(以BluetoothCharacteristic为例):
import 'package:flutter_blue/flutter_blue.dart'; import 'package:hive/hive.dart'; class BluetoothCharacteristicAdapter extends TypeAdapter<BluetoothCharacteristic> { @override final typeId = 2; @override BluetoothCharacteristic read(BinaryReader reader) { // 注意:BluetoothCharacteristic的实例通常依赖于BluetoothService,直接反序列化可能无法正常使用 // 这里仅存储关键标识,实际使用时建议通过设备重新发现 final uuidStr = reader.readString(); final serviceUuidStr = reader.readString(); return BluetoothCharacteristic( uuid: Guid(uuidStr), service: BluetoothService(uuid: Guid(serviceUuidStr), characteristics: []), ); } @override void write(BinaryWriter writer, BluetoothCharacteristic obj) { writer.writeString(obj.uuid.toString()); writer.writeString(obj.service.uuid.toString()); } }
3. 注册所有适配器
在main函数初始化Hive时注册适配器:
void main() async { await Hive.initFlutter(); // 注册自定义适配器 Hive.registerAdapter(BluetoothDeviceAdapter()); Hive.registerAdapter(BluetoothServiceAdapter()); Hive.registerAdapter(BluetoothCharacteristicAdapter()); // 注册你的SavedDevice适配器 Hive.registerAdapter(SavedDeviceAdapter()); runApp(MyApp()); }
方案二:存储设备/服务/特征的标识信息(推荐)
直接存储flutter_blue的对象存在隐患:这些对象包含实时状态信息,序列化后再反序列化的实例可能无法正常用于蓝牙连接。更可靠的方式是只存储唯一标识,需要连接时通过标识重新获取设备和服务。
1. 修改SavedDevice类
只存储关键的字符串标识:
part 'savedDevice.g.dart'; @HiveType(typeId: 0) class SavedDevice extends HiveObject { @HiveField(0) late String characteristicUuid; @HiveField(1) late String serviceUuid; @HiveField(2) late String deviceId; @HiveField(3) late String deviceName; }
2. 存储设备信息
获取到蓝牙设备、服务、特征后,将它们的标识存入Hive:
// 假设已有BluetoothDevice device, BluetoothService service, BluetoothCharacteristic characteristic final savedDevice = SavedDevice() ..deviceId = device.id.toString() ..deviceName = device.name ?? 'Unknown Device' ..serviceUuid = service.uuid.toString() ..characteristicUuid = characteristic.uuid.toString(); // 存入Hive await Hive.box<SavedDevice>('saved_devices').add(savedDevice);
3. 从存储恢复并连接设备
需要连接时,通过存储的标识重新获取设备和服务:
// 从Hive取出SavedDevice final savedDevice = Hive.box<SavedDevice>('saved_devices').getAt(0); if (savedDevice == null) return; // 通过设备ID获取设备实例 final targetDevice = await FlutterBlue.instance.getDevice(DeviceIdentifier(savedDevice.deviceId)); // 连接设备 await targetDevice.connect(); // 发现设备服务 final services = await targetDevice.discoverServices(); // 匹配目标服务 final targetService = services.firstWhere((s) => s.uuid.toString() == savedDevice.serviceUuid); // 匹配目标特征 final targetCharacteristic = targetService.characteristics.firstWhere((c) => c.uuid.toString() == savedDevice.characteristicUuid); // 之后即可使用targetCharacteristic进行读写操作
为什么推荐方案二?
flutter_blue的设备类包含大量实时状态(如连接状态、信号强度等),这些状态无法通过序列化持久化。存储标识信息不仅避免了序列化第三方类的繁琐,还能确保每次连接都获取到最新的设备状态,稳定性和可维护性更高。
内容的提问来源于stack exchange,提问作者snakee67
相关产品推荐
相关产品推荐

