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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 03:45:55