OpenHarmony + Flutter 混合开发进阶:构建支持离线优先、边缘同步与冲突解决的分布式数据应用

引言

在电力巡检、野外勘探、应急救灾等场景中,网络不稳定甚至完全中断是常态。传统"先联网再操作"的模式极易导致:

  • 📉 数据丢失(提交失败未缓存);
  • 业务停滞(无网无法使用);
  • 🔄 多端冲突(同一设备在手机和平板上修改)。

OpenHarmony 提供强大的 分布式数据管理(Distributed Data Management, DDM)关系型数据库(RDB) ,支持跨设备自动同步;而 Flutter 虽有 hiveisar 等本地数据库,但缺乏原生分布式能力

本文将教你如何:

构建"离线优先"架构 :无网时仍可完整操作

打通 Flutter 与 OpenHarmony RDB 分布式表

实现基于时间戳 + CRDT 的自动冲突解决

开发一个"电力设备巡检系统" ,支持 手机录入 → 平板查看 → 后台同步,全程无感。

所有方案基于 OpenHarmony API 10(4.1 SDK) + Flutter 3.19 + Riverpod + Isar,已在华为 MatePad + Pura 70(OpenHarmony 版)组成的分布式设备组实测。


一、核心挑战:离线与分布式的矛盾

需求 Flutter 原生方案 OpenHarmony 原生方案 混合方案
本地存储 ✅ Hive/Isar ✅ RDB ✅ Isar(Flutter)+ RDB(同步桥)
离线操作 ✅ 完全支持 ✅ 支持 ✅ 主流程在 Flutter
跨设备同步 ❌ 无 ✅ DDM 自动同步 ✅ RDB 分布式表作为"同步总线"
冲突解决 ⚠️ 需自研 ✅ 内置 LWW(Last Write Wins) ✅ 扩展为 CRDT

🔑 关键洞察
Flutter 负责 UI 与离线体验,OpenHarmony RDB 负责分布式同步 ,两者通过 双向同步代理 桥接。


二、整体架构设计

复制代码
┌───────────────────────────────┐
│        Flutter (Dart)         │
│  - Isar 本地数据库            │
│  - UI / 业务逻辑              │
│  - 监听同步状态               │
└──────────────▲────────────────┘
               │ 双向同步
┌──────────────┴────────────────┐
│   OpenHarmony Sync Bridge     │ ← MethodChannel + EventChannel
│  - 读写 RDB 分布式表          │
│  - 监听 DDM 数据变更          │
│  - 执行冲突解决策略           │
└──────────────▲────────────────┘
               │
┌──────────────┴────────────────┐
│ OpenHarmony 分布式数据管理 (DDM)│
│  - 自动跨设备同步             │
│  - 设备发现与组网             │
└───────────────────────────────┘

优势

  • 用户始终操作 本地 Isar,响应快、无阻塞;
  • 同步由 后台 RDB 桥 异步完成,对 UI 无感;
  • 利用 OpenHarmony 原生分布式能力,无需自建 MQTT/WebSocket。

三、Step 1:定义统一数据模型

巡检记录模型(JSON Schema)

json 复制代码
{
  "id": "string",           // 全局唯一 ID(UUIDv7)
  "deviceId": "string",     // 设备编号
  "status": "normal|abnormal",
  "notes": "string",
  "timestamp": 1700000000,  // 本地创建时间(Unix ms)
  "synced": false,          // 是否已同步
  "lastModified": 1700000000 // 最后修改时间(用于冲突)
}

💡 使用 UUIDv7(时间有序) 保证全局唯一且可排序。


四、Step 2:Flutter 端 ------ 离线优先数据库(Isar)

dart 复制代码
// lib/models/inspection.dart
part 'inspection.g.dart';

@Collection()
class Inspection {
  Id id = Isar.autoIncrement; // 本地自增 ID(仅用于 Isar)
  late String globalId;       // 全局 UUID
  late String deviceId;
  late String status;
  late String notes;
  late int timestamp;
  late bool synced;
  late int lastModified;

  Inspection({
    required this.globalId,
    required this.deviceId,
    required this.status,
    required this.notes,
    required this.timestamp,
  }) : lastModified = timestamp, synced = false;
}

保存巡检记录(离线可用)

dart 复制代码
// lib/repositories/inspection_repo.dart
Future<void> saveInspection(Inspection record) async {
  // 1. 生成全局 ID(若为新记录)
  if (record.globalId.isEmpty) {
    record.globalId = Uuid().v7();
    record.timestamp = DateTime.now().millisecondsSinceEpoch;
  }
  record.lastModified = DateTime.now().millisecondsSinceEpoch;
  record.synced = false;

  // 2. 保存到 Isar
  await isar.inspections.put(record);

  // 3. 触发同步(异步)
  _triggerSync();
}

五、Step 3:OpenHarmony 端 ------ 分布式 RDB 表

创建分布式表(SecurityLevel.S1 即可)

typescript 复制代码
// model/InspectionModel.ts
const INSPECTION_TABLE_CREATE = `
  CREATE TABLE IF NOT EXISTS inspections (
    global_id TEXT PRIMARY KEY,
    device_id TEXT NOT NULL,
    status TEXT NOT NULL,
    notes TEXT,
    timestamp INTEGER NOT NULL,
    last_modified INTEGER NOT NULL,
    device_hash TEXT NOT NULL  -- 用于冲突识别
  )
`;

// 配置分布式
const STORE_CONFIG: rdb.StoreConfig = {
  name: 'inspection_store.db',
  securityLevel: rdb.SecurityLevel.S1,
  distributed: true, // 关键!启用分布式
};

🌐 distributed: true 使该表自动在 同一用户、同一应用、同一网络 下的设备间同步。


六、Step 4:双向同步桥(核心!)

1. Flutter → OpenHarmony(上传未同步记录)

dart 复制代码
// lib/services/sync_service.dart
Future<void> _uploadPendingRecords() async {
  final pending = await isar.inspections.filter().syncedEqualTo(false).findAll();
  
  for (final record in pending) {
    await _channel.invokeMethod('putInspection', {
      'globalId': record.globalId,
      'deviceId': record.deviceId,
      'status': record.status,
      'notes': record.notes,
      'timestamp': record.timestamp,
      'lastModified': record.lastModified,
    });
    
    // 标记为已同步
    final updated = record.copyWith(synced: true);
    await isar.inspections.put(updated);
  }
}

2. OpenHarmony → Flutter(拉取远程变更)

typescript 复制代码
// EntryAbility.ts
// 监听 RDB 变更(包括远程设备同步来的)
rdbStore.on('dataChange', (mode, uri) => {
  if (uri.tableName === 'inspections') {
    this.syncBridge.pullChangesToFlutter(); // 推送至 Flutter
  }
});

// 拉取并发送给 Flutter
async pullChangesToFlutter() {
  const records = await rdbStore.query(new rdb.RdbPredicates('inspections'));
  const list: any[] = [];
  while (records.goToNextRow()) {
    list.push({
      globalId: records.getString('global_id'),
      deviceId: records.getString('device_id'),
      // ...其他字段
    });
  }
  this.eventChannel.success({ type: 'remote_update', data: list });
}

3. Flutter 接收远程变更

dart 复制代码
// 监听 EventChannel
eventChannel.receiveBroadcastStream().listen((event) {
  if (event['type'] == 'remote_update') {
    final remoteList = (event['data'] as List)
        .map((e) => Inspection.fromJson(e))
        .toList();
    
    // 合并到本地 Isar(触发冲突解决)
    _mergeRemoteRecords(remoteList);
  }
});

七、Step 5:冲突解决策略(超越 LWW)

OpenHarmony RDB 默认使用 LWW(Last Write Wins) ,但业务上可能不合理。

例如:A 设备注"正常",B 设备注"异常",不能简单以时间为准

方案:采用 CRDT(Conflict-Free Replicated Data Type) 思想

对于巡检状态,定义 "异常 > 正常" 的优先级规则。

dart 复制代码
void _resolveConflict(Inspection local, Inspection remote) {
  // 规则1:若任一方为 abnormal,则结果为 abnormal
  final resolvedStatus = (local.status == 'abnormal' || remote.status == 'abnormal')
      ? 'abnormal'
      : 'normal';

  // 规则2:合并备注(避免覆盖)
  final resolvedNotes = _mergeNotes(local.notes, remote.notes);

  // 创建新版本(更新 lastModified)
  final merged = Inspection(
    globalId: local.globalId,
    deviceId: local.deviceId, // 保留原始设备
    status: resolvedStatus,
    notes: resolvedNotes,
    timestamp: local.timestamp, // 创建时间不变
  );

  // 保存合并结果,并标记为已同步
  isar.inspections.put(merged.copyWith(synced: true));
}

String _mergeNotes(String a, String b) {
  if (a == b) return a;
  final set = <String>{...a.split('\n'), ...b.split('\n')}.where((s) => s.trim().isNotEmpty);
  return set.join('\n');
}

🧠 高级扩展 :可引入 向量时钟(Vector Clock) 实现更精确因果序。


八、网络状态感知与自动重试

dart 复制代码
// lib/providers/network_provider.dart
final networkProvider = StreamProvider<NetworkStatus>((ref) {
  return NetworkStatusManager().onStatusChanged();
});

// 在同步服务中监听
ref.listen(networkProvider, (prev, curr) {
  if (curr?.isConnected == true && prev?.isConnected == false) {
    // 网络恢复,立即触发同步
    syncService.syncNow();
  }
});

断网时提示(非阻断)

dart 复制代码
Consumer(builder: (context, ref, child) {
  final offline = !ref.watch(networkProvider).value?.isConnected ?? false;
  return Scaffold(
    body: Stack(
      children: [
        // 主界面
        InspectionForm(),
        // 离线浮层(半透明提示)
        if (offline) OfflineBanner(),
      ],
    ),
  );
});

九、测试场景验证

场景 预期行为
手机无网时新增记录 ✅ 本地保存成功,显示"离线"提示
手机联网后 ✅ 自动同步至 RDB 分布式表
平板在线 ✅ 几秒内收到同步,显示新记录
手机和平板同时修改同一设备 ✅ 触发冲突解决,状态合并为"异常"
删除设备后重新安装 App ✅ 从分布式网络自动恢复历史数据

十、总结:让数据在边缘自由流动

通过本文,你已掌握:

离线优先架构设计

Flutter 与 OpenHarmony RDB 双向同步

基于业务规则的冲突解决

利用 OpenHarmony 原生分布式能力免运维

🌍 未来方向

  • 结合 OpenHarmony 软总线,实现跨 OS(如 Linux 边缘服务器)同步;
  • 引入 差分同步,减少流量消耗;
  • 支持 部分同步(按区域/角色过滤数据)。

在万物分布式时代,数据不应被网络束缚 。通过深度融合 OpenHarmony 的分布式基因与 Flutter 的跨端体验,我们能构建真正 "随时随地、多端一致" 的下一代行业应用。


https://openharmonycrossplatform.csdn.net/content

相关推荐
克喵的水银蛇2 小时前
Flutter 通用底部导航栏:BottomNavWidget 一键实现样式统一与灵活切换
windows·flutter
小白|2 小时前
OpenHarmony + Flutter 混合开发实战:深度集成 Health Kit 实现跨设备健康数据同步与隐私保护
flutter
ujainu3 小时前
Flutter实战避坑指南:从架构设计到性能优化的全链路方案
flutter
张人玉3 小时前
大数据hadoop系列——在ubuntu上安装HBase 伪分布式
大数据·hadoop·分布式·hbase
解局易否结局3 小时前
Flutter:跨平台开发的“效率与体验”双优解
flutter
永远都不秃头的程序员(互关)3 小时前
鸿蒙Electron平台:Flutter技术深度解读及学习笔记
笔记·学习·flutter
闲人编程4 小时前
API限流、鉴权与监控
分布式·python·wpf·限流·集群·令牌·codecapsule
tangweiguo030519874 小时前
Riverpod 2.x 完全指南:从 StateNotifierProvider 到现代状态管理
flutter
苦学编程的谢4 小时前
RabbitMQ_4_高级特性(1)
分布式·rabbitmq