【OpenHarmony × Flutter】混合开发高阶实战:如何统一管理跨平台状态?Riverpod + ArkTS 共享数据流架构详解

---

一、痛点:混合应用为何"数据割裂"?

在 OpenHarmony + Flutter 混合开发中,开发者常陷入 "双状态地狱"

  • 📱 用户登录后,Flutter 页面显示"已登录",但原生通知插件仍用旧 Token 请求失败;
  • 🔔 手表点击"稍后处理",手机 Flutter 页面未刷新待办列表;
  • 🌐 多设备协同编辑文档,平板保存后,手机端仍显示旧内容;
  • 🧩 状态分散在 Dart、ArkTS、SharedPreferences、Ability Context 中,难以追踪和调试。

根本原因缺乏统一的状态源(Single Source of Truth) ,且 跨语言数据同步机制缺失


二、目标:构建"一次写入,处处响应"的共享状态架构

我们要实现:

Dart 与 ArkTS 共享同一份业务状态 (如用户信息、待办列表);

任一端修改状态,另一端自动响应 (无需手动刷新);

支持持久化 + 跨设备同步

兼容 Riverpod 的响应式编程模型


三、整体架构设计

复制代码
┌───────────────────────────────┐
│        Shared State Store     │ ← 核心:统一状态容器
│  - 用户信息                   │
│  - 待办列表                   │
│  - 文档草稿                   │
└──────────────▲────────────────┘
               │ (双向同步)
┌──────────────┴────────────────┐      ┌──────────────────────┐
│   Flutter (Dart)              │      │ OpenHarmony (ArkTS)  │
│  - Riverpod Provider          │◄────►│  - Observed State    │
│  - 自动 rebuild UI            │      │  - 触发原生操作      │
└───────────────────────────────┘      └──────────────────────┘
               ▲                                   ▲
               │ (持久化)                          │ (持久化)
        ┌──────┴───────┐                  ┌────────┴─────────┐
        │  SecureStorage│                  │  Preferences Kit │
        └──────────────┘                  └──────────────────┘

💡 核心思想
状态不归属任何一方,而是由一个"中间层"托管,并通过事件总线双向同步


四、Step 1:定义共享状态模型(JSON Schema)

首先约定 跨平台通用数据结构(使用 JSON 兼容格式):

json 复制代码
// shared_models/user.json
{
  "userId": "string",
  "name": "string",
  "avatarUri": "string?",
  "isLoggedIn": "boolean"
}

// shared_models/todo.json
{
  "id": "string",
  "title": "string",
  "isCompleted": "boolean",
  "createdAt": "number" // timestamp
}

✅ 所有字段必须为 基本类型或数组/对象嵌套,避免平台特有类型。


五、Step 2:在 OpenHarmony 端实现状态存储与监听

ohos/src/main/ets/SharedStateStore.ets

typescript 复制代码
import preferences from '@ohos.data.preferences';
import context from '@ohos.app.ability.context';
import { emitter } from '@ohos.events.emitter';

// 事件 ID(与 Flutter 约定)
const EVENT_USER_UPDATE = 1001;
const EVENT_TODO_UPDATE = 1002;

export class SharedStateStore {
  private pref: preferences.Preferences;
  private static instance: SharedStateStore | null = null;

  private constructor(private ctx: context.Context) {
    this.pref = preferences.getPreferences(this.ctx, 'shared_state');
  }

  static getInstance(ctx?: context.Context): SharedStateStore {
    if (!SharedStateStore.instance && ctx) {
      SharedStateStore.instance = new SharedStateStore(ctx);
    }
    return SharedStateStore.instance!;
  }

  // 获取用户信息
  async getUser(): Promise<Record<string, any> | null> {
    const jsonStr = this.pref.get('user', '');
    return jsonStr ? JSON.parse(jsonStr) : null;
  }

  // 更新用户并广播
  async setUser(user: Record<string, any>): Promise<void> {
    await this.pref.put('user', JSON.stringify(user));
    await this.pref.flush();

    // 广播事件(Flutter 会监听)
    emitter.emit({ event: EVENT_USER_UPDATE, data: user });
    console.info('[SharedState] User updated and emitted');
  }

  // 获取待办列表
  async getTodos(): Promise<Array<Record<string, any>>> {
    const jsonStr = this.pref.get('todos', '[]');
    return JSON.parse(jsonStr);
  }

  // 添加待办
  async addTodo(todo: Record<string, any>): Promise<void> {
    const todos = await this.getTodos();
    todos.push(todo);
    await this.pref.put('todos', JSON.stringify(todos));
    await this.pref.flush();

    emitter.emit({ event: EVENT_TODO_UPDATE, data: todos });
  }

  // 订阅事件(供 Flutter 初始化后注册)
  subscribe(eventId: number, callback: (data: any) => void): void {
    emitter.on({ event: eventId }, callback);
  }

  // 取消订阅
  unsubscribe(eventId: number): void {
    emitter.off({ event: eventId });
  }
}

🔒 安全说明

  • 使用 @ohos.data.preferences 实现 加密持久化(需开启 secure 模式);
  • 所有数据以 JSON 字符串 存储,确保跨平台兼容。

六、Step 3:在 Flutter 端封装共享状态服务

1. 定义 Dart 模型(与 ArkTS 保持一致)

dart 复制代码
// lib/models/user.dart
class User {
  final String userId;
  final String name;
  final String? avatarUri;
  final bool isLoggedIn;

  User({
    required this.userId,
    required this.name,
    this.avatarUri,
    required this.isLoggedIn,
  });

  factory User.fromJson(Map<String, dynamic> json) => User(
        userId: json['userId'] as String,
        name: json['name'] as String,
        avatarUri: json['avatarUri'] as String?,
        isLoggedIn: json['isLoggedIn'] as bool,
      );

  Map<String, dynamic> toJson() => {
        'userId': userId,
        'name': name,
        'avatarUri': avatarUri,
        'isLoggedIn': isLoggedIn,
      };
}

2. 创建共享状态 Bridge(通过 MethodChannel + EventChannel)

dart 复制代码
// lib/core/shared_state_bridge.dart
import 'package:flutter/services.dart';

class SharedStateBridge {
  static const _methodChannel = MethodChannel('com.example.shared_state/methods');
  static const _eventChannel = EventChannel('com.example.shared_state/events');

  // 初始化(主工程调用)
  static Future<void> initialize() async {
    await _methodChannel.invokeMethod('initialize');
  }

  // 获取用户
  static Future<User?> getUser() async {
    final json = await _methodChannel.invokeMethod('getUser') as String?;
    return json != null ? User.fromJson(jsonDecode(json)) : null;
  }

  // 设置用户
  static Future<void> setUser(User user) async {
    await _methodChannel.invokeMethod('setUser', user.toJson());
  }

  // 监听用户变更(返回 Stream)
  static Stream<User> onUserUpdate() {
    return _eventChannel.receiveBroadcastStream('user')
        .map((event) => User.fromJson(event as Map<String, dynamic>));
  }

  // 监听待办变更
  static Stream<List<Todo>> onTodoUpdate() {
    return _eventChannel.receiveBroadcastStream('todo')
        .map((event) => (event as List).map((e) => Todo.fromJson(e)).toList());
  }
}

3. 实现 Riverpod Provider

dart 复制代码
// lib/providers/shared_state_provider.dart
final userProvider = StreamProvider<User?>((ref) {
  // 首次加载
  ref.onDispose(() {
    // 可选:清理
  });
  return SharedStateBridge.onUserUpdate().asyncMap((user) async {
    return user;
  });
});

// 或使用 StateNotifier(更灵活)
class UserNotifier extends StateNotifier<User?> {
  UserNotifier() : super(null) {
    _loadInitialUser();
    _listenToUpdates();
  }

  Future<void> _loadInitialUser() async {
    final user = await SharedStateBridge.getUser();
    state = user;
  }

  void _listenToUpdates() {
    SharedStateBridge.onUserUpdate().listen((user) {
      state = user;
    });
  }

  Future<void> updateUser(User newUser) async {
    await SharedStateBridge.setUser(newUser);
    // 不需要手动 setState,事件会自动触发
  }
}

final userNotifierProvider = StateNotifierProvider<UserNotifier, User?>((ref) {
  return UserNotifier();
});

七、Step 4:双向同步机制打通

OpenHarmony 端:接收 Flutter 的状态变更请求

typescript 复制代码
// MainAbility.ets 中注册 MethodChannel
flutter.MethodChannel('com.example.shared_state/methods')
  .setMethodCallHandler(async (call) => {
    const store = SharedStateStore.getInstance();

    switch (call.method) {
      case 'initialize':
        // 初始化完成
        return Promise.resolve(true);

      case 'getUser':
        const user = await store.getUser();
        return Promise.resolve(user ? JSON.stringify(user) : null);

      case 'setUser':
        await store.setUser(call.args as Record<string, any>);
        return Promise.resolve(true);

      default:
        return Promise.reject('Not implemented');
    }
  });

// 同时,将 emitter 事件转发给 Flutter(通过 EventChannel)
const eventChannel = new flutter.EventChannel('com.example.shared_state/events');
eventChannel.setStreamHandler({
  onListen: (arguments) => {
    const eventType = arguments as string;
    const eventId = eventType === 'user' ? 1001 : 1002;

    // 注册监听(emitter → Flutter)
    SharedStateStore.getInstance().subscribe(eventId, (data) => {
      eventChannel.send(data); // 推送数据
    });
    return Promise.resolve();
  },
  onCancel: () => {
    // 取消监听
    return Promise.resolve();
  }
});

关键逻辑

  • Flutter 通过 MethodChannel 写入状态
  • OpenHarmony 通过 emitter 广播变更
  • Flutter 通过 EventChannel 接收广播 → 自动 rebuild。

八、实战:用户登录状态同步

场景:用户在 Flutter 页面点击"登录"

dart 复制代码
// 登录按钮回调
onPressed: () async {
  final user = await loginApi(); // 假设已获取用户数据
  // 更新共享状态
  ref.read(userNotifierProvider.notifier).updateUser(user);
  // 此时:
  // 1. OpenHarmony Preferences 被更新
  // 2. 手表/平板上的原生组件收到新用户数据
  // 3. 手机 Flutter 页面自动刷新(因 Stream 触发)
}

原生侧(如通知插件)使用最新用户:

typescript 复制代码
// notification_ohos 插件中
const user = await SharedStateStore.getInstance().getUser();
if (user?.isLoggedIn) {
  sendNotification(`欢迎回来,${user.name}!`);
}

九、高级能力扩展

1. 跨设备状态同步

  • Preferences 替换为 DistributedDataManager
  • 状态变更时自动同步到同一账号下的其他设备。

2. 离线优先

  • 本地状态立即生效,网络请求异步提交;
  • 冲突解决策略:最后写入胜出(LWW)自定义合并函数

3. 调试工具

  • 提供 状态快照导出 功能(用于 bug 复现);
  • 在 DevTools 中集成 Shared State Inspector

十、总结

通过本文,你已掌握:

构建 Dart 与 ArkTS 共享的状态中心

利用 Riverpod + emitter 实现响应式数据流

打破混合应用的数据孤岛

为多设备协同提供统一状态基础

🚀 适用场景

  • 企业办公(统一身份+待办)
  • 智慧医疗(患者档案跨端同步)
  • 政务服务(电子证照状态一致)

真正的混合开发,不是 UI 的拼接,而是数据的融合。只有状态统一,体验才能无缝。


https://openharmonycrossplatform.csdn.net/content

相关推荐
虚伪的空想家1 小时前
arm架构TDengine时序数据库及应用使用K8S部署
服务器·arm开发·架构·kubernetes·arm·时序数据库·tdengine
拾忆,想起1 小时前
Dubbo服务降级全攻略:构建韧性微服务系统的守护盾
java·前端·网络·微服务·架构·dubbo
闲人编程1 小时前
FastAPI框架架构与设计哲学
python·架构·api·fastapi·异步·codecapsule
kirk_wang1 小时前
Flutter connectivity_plus 在鸿蒙端的完整适配指南:从原理到实践
flutter·移动开发·跨平台·arkts·鸿蒙
weixin_307779131 小时前
简化多维度测试:Jenkins Matrix Project 的核心概念与最佳实践
运维·开发语言·架构·jenkins
weixin_307779131 小时前
Jenkins Matrix Authorization Strategy插件:详解与应用指南
运维·开发语言·架构·jenkins
帅气马战的账号1 小时前
开源鸿蒙+Flutter 分布式组件通信与状态一致性保障指南
flutter
SadSunset1 小时前
(16)MyBatis执行流程分析(偏上层架构)
java·架构·mybatis
吃好喝好玩好睡好1 小时前
OpenHarmony 分布式环境下 Electron+Flutter 应用的增量更新设计
分布式·flutter·eclipse·electron