前言

随着鸿蒙 OS(HarmonyOS)生态的持续扩张,其核心的分布式能力(如多设备协同、跨终端数据同步、分布式任务调度)已成为区别于其他操作系统的核心优势。而 Flutter 作为跨平台开发的主流框架,凭借 “一次开发、多端部署” 的特性,被广泛应用于移动应用、桌面应用甚至嵌入式设备开发。

当 Flutter 遇上鸿蒙分布式能力,开发者可以快速构建 “一套代码、多设备协同” 的跨终端应用 —— 比如手机拍摄的照片实时同步到平板编辑、手表控制电视播放、多设备共享同一个任务清单。本文将从环境搭建、核心能力解析、实战开发、问题排查四个维度,手把手教你如何在 Flutter 项目中接入鸿蒙分布式能力,实现多设备协同与数据同步,附带完整代码示例和官方文档链接,助力开发者快速落地相关场景。

本文核心价值

  1. 详解鸿蒙分布式能力的核心概念与 Flutter 集成原理;
  2. 提供可直接运行的代码示例(Flutter 端 + 鸿蒙原生端);
  3. 实战搭建 “多设备协同任务清单” 应用,覆盖设备发现、数据同步、协同操作全流程;
  4. 整理常见问题与解决方案,避免踩坑;
  5. 附上官方文档、工具下载、API 参考等权威链接。

适用人群

  • Flutter 开发者想拓展鸿蒙生态应用;
  • 鸿蒙开发者想集成 Flutter 提升跨端开发效率;
  • 对跨终端协同、分布式技术感兴趣的技术人员。

前置知识储备

  1. 熟悉 Flutter 基础开发(Widget、State 管理、MethodChannel);
  2. 了解鸿蒙 OS 基本概念(Ability、ArkUI、分布式软总线);
  3. 掌握 Android/iOS 原生开发基础(用于理解 Flutter 与鸿蒙原生通信)。

一、鸿蒙分布式能力核心概念解析

在集成前,我们需要先明确鸿蒙分布式能力的核心组件,这是后续开发的基础。官方文档对分布式能力的定义是:通过分布式软总线、分布式数据管理、分布式任务调度等技术,将多个物理设备虚拟成一个 “超级终端”,实现资源共享、能力互助、数据协同

1.1 三大核心分布式能力

能力模块 核心作用 典型应用场景
分布式软总线 设备间高速通信的 “无形网线”,支持 Wi-Fi、蓝牙、NFC 等多协议融合,低延迟、高带宽 设备发现、文件传输、实时数据流传输(如投屏)
分布式数据管理 跨设备数据同步与共享,支持数据订阅 / 发布、分布式数据库 多设备任务清单同步、跨端配置共享、实时数据更新
分布式任务调度 将应用的不同任务模块分发到不同设备执行,实现 “任务迁移” 或 “多设备协同执行” 视频通话时将画面迁移到电视、手机发起计算任务由平板执行

1.2 Flutter 与鸿蒙分布式能力的集成原理

Flutter 本身不直接提供鸿蒙分布式能力的 API,因此需要通过 **“Flutter ↔ 鸿蒙原生” 的通信桥梁 ** 实现能力调用,核心依赖以下技术:

  1. MethodChannel:Flutter 与鸿蒙原生(ArkTS/Java)之间的同步 / 异步通信通道,用于 Flutter 调用鸿蒙原生的分布式 API;
  2. EventChannel:用于鸿蒙原生向 Flutter 推送实时事件(如设备发现结果、数据同步通知);
  3. 鸿蒙原生能力封装:将鸿蒙分布式 API(如 DeviceManager、DistributedDataManager)封装成 Flutter 可调用的接口。

集成架构图如下(建议保存备用):

plaintext

┌─────────────────┐      ┌─────────────────────────────┐
│   Flutter端     │      │          鸿蒙原生端          │
│                 │      │                             │
│  Flutter UI层   │ ←→   │  MethodChannel/EventChannel  │
│  业务逻辑层     │      │  (通信桥梁)                │
│                 │      │                             │
└─────────────────┘      │  分布式能力封装层            │
                         │  (DeviceManager、DistributedDataManager等) │
                         │                             │
                         │  鸿蒙分布式能力底层          │
                         └─────────────────────────────┘

1.3 关键官方文档链接(必看)

二、开发环境搭建

2.1 环境要求

工具 / 组件 版本要求 下载链接
鸿蒙 DevEco Studio 4.0+ DevEco Studio 下载
Flutter SDK 3.10+ Flutter 官方下载
鸿蒙 OS 模拟器 API Version 9+ 需在 DevEco Studio 中安装(Tools → Device Manager)
JDK 17+ JDK 下载
HarmonyOS SDK API Version 9+ 在 DevEco Studio 中自动下载(File → Project Structure → SDK Location)

2.2 环境搭建步骤

步骤 1:安装鸿蒙 DevEco Studio 并配置 SDK
  1. 下载并安装 DevEco Studio 4.0+,安装过程中勾选 “HarmonyOS SDK”;
  2. 打开 DevEco Studio,进入File → Settings → Appearance & Behavior → System Settings → HarmonyOS SDK,勾选 API Version 9 及以上版本的 SDK(包括 “Distributed Capability” 模块),点击 “Apply” 自动下载。
步骤 2:安装 Flutter SDK 并配置鸿蒙支持
  1. 下载 Flutter SDK,解压后配置环境变量(如 Windows 添加FLUTTER_HOME,并将bin目录加入 Path);
  2. 打开终端,执行flutter doctor检查环境,确保无关键错误;
  3. 执行flutter config --enable-harmony启用鸿蒙支持(需 Flutter 3.10 + 版本);
  4. 验证 Flutter 与鸿蒙的兼容性:执行flutter create --template=harmony my_flutter_harmony,创建一个默认的 Flutter + 鸿蒙项目,若能正常编译则配置成功。
步骤 3:配置鸿蒙模拟器(多设备)

由于需要测试多设备协同,需创建至少 2 个鸿蒙模拟器:

  1. 打开 DevEco Studio,点击顶部Tools → Device Manager
  2. 点击 “Create Device”,选择不同的设备类型(如 Phone、Tablet),选择 API Version 9+,完成创建;
  3. 启动 2 个模拟器,确保它们处于同一网络(如默认的模拟器网络),后续用于测试设备发现和数据同步。

2.3 项目初始化(Flutter + 鸿蒙分布式能力)

步骤 1:创建鸿蒙原生项目(作为宿主工程)
  1. 打开 DevEco Studio,创建一个 “Empty Ability” 项目,选择 “HarmonyOS” 作为系统,API Version 9+;
  2. 项目名称:harmony_distributed_host,包名:com.example.harmony_distributed_host
步骤 2:集成 Flutter 模块
  1. 在终端执行flutter create -t module flutter_module,创建 Flutter 模块(与鸿蒙项目同级目录);
  2. 打开鸿蒙项目的build.gradle(Module 级),添加 Flutter 依赖:

gradle

dependencies {
    // 集成Flutter模块
    implementation project(':flutter_module')
    // 鸿蒙分布式能力依赖
    implementation 'com.huawei.hms:distributeddevice:4.0.0.300'
    implementation 'com.huawei.hms:distributeddb:4.0.0.300'
}
  1. 在鸿蒙项目的settings.gradle中添加 Flutter 模块引用:

gradle

include ':flutter_module'
project(':flutter_module').projectDir = new File(rootProject.projectDir, '../flutter_module')
  1. 同步项目(Sync Now),确保依赖下载成功。
步骤 3:配置分布式能力权限

在鸿蒙项目的config.json中添加分布式能力所需权限(关键!否则无法调用 API):

json

"module": {
    "reqPermissions": [
        {
            "name": "ohos.permission.DISTRIBUTED_DEVICE_DISCOVER", // 设备发现权限
            "reason": "用于发现周边鸿蒙设备",
            "usedScene": {
                "ability": ["com.example.harmony_distributed_host.MainAbility"],
                "when": "always"
            }
        },
        {
            "name": "ohos.permission.DISTRIBUTED_DATA_MANAGER", // 分布式数据管理权限
            "reason": "用于跨设备数据同步",
            "usedScene": {
                "ability": ["com.example.harmony_distributed_host.MainAbility"],
                "when": "always"
            }
        },
        {
            "name": "ohos.permission.INTERNET", // 网络权限(分布式软总线依赖)
            "reason": "用于设备间通信",
            "usedScene": {
                "ability": ["com.example.harmony_distributed_host.MainAbility"],
                "when": "always"
            }
        }
    ]
}

三、核心能力接入实战:Flutter 调用鸿蒙分布式 API

3.1 通信桥梁搭建:Flutter ↔ 鸿蒙原生

Flutter 无法直接调用鸿蒙原生 API,需通过MethodChannel(同步 / 异步调用)和EventChannel(原生向 Flutter 推送事件)实现通信。我们先封装一个统一的通信工具类。

3.1.1 鸿蒙原生端:通信通道初始化

创建FlutterDistributedChannel类,负责与 Flutter 端通信,并封装分布式 API 调用:

java

运行

package com.example.harmony_distributed_host;

import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.FlutterEngineCache;
import io.flutter.embedding.engine.dart.DartExecutor;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.EventChannel;

public class MainAbility extends Ability {
    // 定义MethodChannel和EventChannel名称(需与Flutter端一致)
    private static final String METHOD_CHANNEL_NAME = "com.example.distributed/method";
    private static final String EVENT_CHANNEL_DEVICE = "com.example.distributed/device_event";
    private static final String EVENT_CHANNEL_DATA = "com.example.distributed/data_event";

    private MethodChannel methodChannel;
    private EventChannel.EventSink deviceEventSink; // 设备发现事件回调
    private EventChannel.EventSink dataEventSink; // 数据同步事件回调

    // 分布式能力核心对象(后续初始化)
    private DistributedDeviceManager deviceManager;
    private DistributedDataManager dataManager;

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        // 初始化Flutter引擎
        initFlutterEngine();
        // 初始化分布式能力管理器
        initDistributedManagers();
        // 初始化通信通道
        initCommunicationChannels();
    }

    /**
     * 初始化Flutter引擎
     */
    private void initFlutterEngine() {
        FlutterEngine flutterEngine = new FlutterEngine(this);
        flutterEngine.getDartExecutor().executeDartEntrypoint(
                DartExecutor.DartEntrypoint.createDefault()
        );
        FlutterEngineCache.getInstance().put("my_flutter_engine", flutterEngine);
    }

    /**
     * 初始化分布式设备管理器和数据管理器
     */
    private void initDistributedManagers() {
        // 初始化设备管理器(用于设备发现、连接)
        deviceManager = DistributedDeviceManager.getInstance(this);
        // 初始化数据管理器(用于分布式数据同步)
        dataManager = DistributedDataManager.getInstance(this);
    }

    /**
     * 初始化MethodChannel和EventChannel
     */
    private void initCommunicationChannels() {
        FlutterEngine flutterEngine = FlutterEngineCache.getInstance().get("my_flutter_engine");
        if (flutterEngine == null) return;

        // 1. MethodChannel:处理Flutter端的方法调用
        methodChannel = new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), METHOD_CHANNEL_NAME);
        methodChannel.setMethodCallHandler((call, result) -> {
            switch (call.method) {
                case "startDeviceDiscovery": // 开始设备发现
                    startDeviceDiscovery(result);
                    break;
                case "stopDeviceDiscovery": // 停止设备发现
                    stopDeviceDiscovery(result);
                    break;
                case "syncData": // 同步数据到分布式网络
                    String data = call.argument("data");
                    syncData(data, result);
                    break;
                case "querySyncData": // 查询同步数据
                    querySyncData(result);
                    break;
                default:
                    result.notImplemented();
            }
        });

        // 2. EventChannel:设备发现事件(原生→Flutter)
        new EventChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), EVENT_CHANNEL_DEVICE)
                .setStreamHandler(new EventChannel.StreamHandler() {
                    @Override
                    public void onListen(Object arguments, EventSink events) {
                        deviceEventSink = events; // 保存事件回调,用于后续推送设备信息
                    }

                    @Override
                    public void onCancel(Object arguments) {
                        deviceEventSink = null;
                    }
                });

        // 3. EventChannel:数据同步事件(原生→Flutter)
        new EventChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), EVENT_CHANNEL_DATA)
                .setStreamHandler(new EventChannel.StreamHandler() {
                    @Override
                    public void onListen(Object arguments, EventSink events) {
                        dataEventSink = events; // 保存事件回调,用于推送数据更新
                    }

                    @Override
                    public void onCancel(Object arguments) {
                        dataEventSink = null;
                    }
                });
    }

    // ------------------------------ 以下为分布式能力具体实现 ------------------------------
    /**
     * 开始设备发现
     */
    private void startDeviceDiscovery(MethodChannel.Result result) {
        try {
            // 注册设备发现回调
            deviceManager.registerDeviceDiscoveryCallback(new DeviceDiscoveryCallback() {
                @Override
                public void onDeviceFound(String deviceId, String deviceName, int deviceType) {
                    // 发现设备,通过EventSink推送给Flutter端
                    if (deviceEventSink != null) {
                        deviceEventSink.success("{\"deviceId\":\"" + deviceId + "\",\"deviceName\":\"" + deviceName + "\",\"deviceType\":\"" + deviceType + "\"}");
                    }
                }

                @Override
                public void onDiscoveryFailed(int errorCode) {
                    if (deviceEventSink != null) {
                        deviceEventSink.error("DISCOVERY_FAILED", "设备发现失败,错误码:" + errorCode, null);
                    }
                }
            });
            // 启动设备扫描(扫描类型:附近的鸿蒙设备)
            deviceManager.startDeviceDiscovery(DeviceFilter.ALL);
            result.success(true);
        } catch (Exception e) {
            result.error("DISCOVERY_EXCEPTION", "设备发现异常:" + e.getMessage(), null);
        }
    }

    /**
     * 停止设备发现
     */
    private void stopDeviceDiscovery(MethodChannel.Result result) {
        try {
            deviceManager.stopDeviceDiscovery();
            result.success(true);
        } catch (Exception e) {
            result.error("STOP_DISCOVERY_EXCEPTION", "停止设备发现异常:" + e.getMessage(), null);
        }
    }

    /**
     * 同步数据到分布式网络
     */
    private void syncData(String data, MethodChannel.Result result) {
        try {
            if (data == null || data.isEmpty()) {
                result.error("DATA_EMPTY", "同步数据不能为空", null);
                return;
            }
            // 创建分布式数据条目(key为"sync_data",value为传入的数据)
            DistributedDataEntry entry = new DistributedDataEntry();
            entry.setKey("sync_data");
            entry.setValue(data.getBytes());
            // 同步数据到分布式网络(所有已连接的设备都会收到)
            dataManager.putData(entry, new PutDataCallback() {
                @Override
                public void onSuccess() {
                    result.success(true);
                    // 推送数据同步成功事件到Flutter端
                    if (dataEventSink != null) {
                        dataEventSink.success("数据同步成功:" + data);
                    }
                }

                @Override
                public void onFailure(int errorCode) {
                    result.error("SYNC_FAILED", "数据同步失败,错误码:" + errorCode, null);
                }
            });
        } catch (Exception e) {
            result.error("SYNC_EXCEPTION", "数据同步异常:" + e.getMessage(), null);
        }
    }

    /**
     * 查询同步数据
     */
    private void querySyncData(MethodChannel.Result result) {
        try {
            // 从分布式网络查询key为"sync_data"的数据
            dataManager.getData("sync_data", new GetDataCallback() {
                @Override
                public void onSuccess(byte[] value) {
                    if (value != null) {
                        String data = new String(value);
                        result.success(data);
                    } else {
                        result.success(""); // 无数据返回空字符串
                    }
                }

                @Override
                public void onFailure(int errorCode) {
                    result.error("QUERY_FAILED", "查询同步数据失败,错误码:" + errorCode, null);
                }
            });
        } catch (Exception e) {
            result.error("QUERY_EXCEPTION", "查询同步数据异常:" + e.getMessage(), null);
        }
    }

    @Override
    public void onStop() {
        super.onStop();
        // 停止设备发现,释放资源
        if (deviceManager != null) {
            deviceManager.stopDeviceDiscovery();
        }
    }
}
3.1.2 Flutter 端:通信工具类封装

在 Flutter 模块中创建distributed_channel.dart,封装 MethodChannel 和 EventChannel 的调用:

dart

import 'package:flutter/services.dart';

class DistributedChannel {
  // 与原生端一致的通道名称
  static const MethodChannel _methodChannel = MethodChannel('com.example.distributed/method');
  static const EventChannel _deviceEventChannel = EventChannel('com.example.distributed/device_event');
  static const EventChannel _dataEventChannel = EventChannel('com.example.distributed/data_event');

  // 设备发现事件流(供UI层监听)
  Stream<Map<String, dynamic>> get deviceDiscoveryStream => _deviceEventChannel
      .receiveBroadcastStream()
      .map((event) => Map<String, dynamic>.from(eval(event.toString())))
      .handleError((error) => throw error);

  // 数据同步事件流(供UI层监听)
  Stream<String> get dataSyncStream => _dataEventChannel
      .receiveBroadcastStream()
      .map((event) => event.toString())
      .handleError((error) => throw error);

  // 解析JSON字符串(简化版,实际项目建议用json_serializable)
  static Map<String, dynamic> eval(String jsonStr) {
    try {
      return _parseJson(jsonStr);
    } catch (e) {
      throw FormatException("JSON解析失败:$jsonStr");
    }
  }

  static Map<String, dynamic> _parseJson(String jsonStr) {
    // 简单JSON解析(实际项目推荐使用dart:convert)
    jsonStr = jsonStr.replaceAll('{', '').replaceAll('}', '').replaceAll('"', '');
    final Map<String, dynamic> map = {};
    for (final entry in jsonStr.split(',')) {
      final parts = entry.split(':');
      if (parts.length == 2) {
        map[parts[0].trim()] = parts[1].trim();
      }
    }
    return map;
  }

  /// 开始设备发现
  Future<bool> startDeviceDiscovery() async {
    try {
      final bool result = await _methodChannel.invokeMethod('startDeviceDiscovery');
      return result;
    } on PlatformException catch (e) {
      throw Exception("开始设备发现失败:${e.message}");
    }
  }

  /// 停止设备发现
  Future<bool> stopDeviceDiscovery() async {
    try {
      final bool result = await _methodChannel.invokeMethod('stopDeviceDiscovery');
      return result;
    } on PlatformException catch (e) {
      throw Exception("停止设备发现失败:${e.message}");
    }
  }

  /// 同步数据到分布式网络
  Future<bool> syncData(String data) async {
    try {
      final bool result = await _methodChannel.invokeMethod('syncData', {'data': data});
      return result;
    } on PlatformException catch (e) {
      throw Exception("数据同步失败:${e.message}");
    }
  }

  /// 查询同步数据
  Future<String> querySyncData() async {
    try {
      final String result = await _methodChannel.invokeMethod('querySyncData');
      return result;
    } on PlatformException catch (e) {
      throw Exception("查询同步数据失败:${e.message}");
    }
  }
}

3.2 实战 1:多设备发现与状态监听

3.2.1 Flutter UI 层实现

创建device_discovery_page.dart,实现设备发现按钮、设备列表展示:

dart

import 'package:flutter/material.dart';
import 'distributed_channel.dart';

class DeviceDiscoveryPage extends StatefulWidget {
  const DeviceDiscoveryPage({super.key});

  @override
  State<DeviceDiscoveryPage> createState() => _DeviceDiscoveryPageState();
}

class _DeviceDiscoveryPageState extends State<DeviceDiscoveryPage> {
  final DistributedChannel _distributedChannel = DistributedChannel();
  List<Map<String, dynamic>> _discoveredDevices = [];
  bool _isDiscovering = false;
  String _log = "";

  @override
  void initState() {
    super.initState();
    // 监听设备发现事件
    _listenDeviceDiscoveryEvents();
  }

  /// 监听设备发现事件
  void _listenDeviceDiscoveryEvents() {
    _distributedChannel.deviceDiscoveryStream.listen(
      (device) {
        setState(() {
          // 避免重复添加同一设备
          if (!_discoveredDevices.any((d) => d['deviceId'] == device['deviceId'])) {
            _discoveredDevices.add(device);
          }
          _log = "发现新设备:${device['deviceName']}(ID:${device['deviceId']})";
        });
      },
      onError: (error) {
        setState(() {
          _log = "设备发现错误:$error";
          _isDiscovering = false;
        });
      },
    );
  }

  /// 开始/停止设备发现
  Future<void> _toggleDeviceDiscovery() async {
    if (_isDiscovering) {
      // 停止发现
      final result = await _distributedChannel.stopDeviceDiscovery();
      if (result) {
        setState(() {
          _isDiscovering = false;
          _log = "已停止设备发现";
        });
      }
    } else {
      // 开始发现
      setState(() {
        _discoveredDevices.clear();
        _log = "正在扫描周边设备...";
      });
      try {
        final result = await _distributedChannel.startDeviceDiscovery();
        if (result) {
          setState(() {
            _isDiscovering = true;
          });
        }
      } catch (e) {
        setState(() {
          _log = "启动设备发现失败:$e";
        });
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("多设备发现"),
        backgroundColor: Colors.blueAccent,
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // 设备发现按钮
            ElevatedButton(
              onPressed: _toggleDeviceDiscovery,
              style: ElevatedButton.styleFrom(
                backgroundColor: _isDiscovering ? Colors.red : Colors.blue,
                padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
              ),
              child: Text(
                _isDiscovering ? "停止扫描" : "开始扫描设备",
                style: const TextStyle(fontSize: 16, color: Colors.white),
              ),
            ),
            const SizedBox(height: 20),
            // 日志信息
            Text(
              "状态:$_log",
              style: const TextStyle(fontSize: 14, color: Colors.grey[700]),
            ),
            const SizedBox(height: 20),
            // 已发现设备列表
            const Text(
              "已发现设备:",
              style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
            ),
            const SizedBox(height: 10),
            _discoveredDevices.isEmpty
                ? const Center(child: Text("暂无设备"))
                : Expanded(
                    child: ListView.builder(
                      itemCount: _discoveredDevices.length,
                      itemBuilder: (context, index) {
                        final device = _discoveredDevices[index];
                        return ListTile(
                          leading: const Icon(Icons.device_hub, color: Colors.blueAccent),
                          title: Text(device['deviceName'] ?? "未知设备"),
                          subtitle: Text("设备ID:${device['deviceId']}\n设备类型:${_getDeviceType(device['deviceType'])}"),
                          trailing: const Icon(Icons.check_circle, color: Colors.green),
                        );
                      },
                    ),
                  ),
          ],
        ),
      ),
    );
  }

  /// 解析设备类型
  String _getDeviceType(String? typeStr) {
    if (typeStr == null) return "未知";
    final int type = int.tryParse(typeStr) ?? 0;
    switch (type) {
      case 1:
        return "手机";
      case 2:
        return "平板";
      case 3:
        return "手表";
      case 4:
        return "电视";
      default:
        return "其他设备";
    }
  }
}
3.2.2 测试效果
  1. 启动 2 个鸿蒙模拟器(手机 + 平板);
  2. 运行 Flutter 项目(在 DevEco Studio 中点击 “Run”);
  3. 进入 “多设备发现” 页面,点击 “开始扫描设备”;
  4. 稍等片刻,即可在列表中看到另一个模拟器设备,日志显示 “发现新设备”。

3.3 实战 2:分布式数据同步

3.3.1 Flutter UI 层实现

创建data_sync_page.dart,实现数据输入、同步、查询功能:

dart

import 'package:flutter/material.dart';
import 'distributed_channel.dart';

class DataSyncPage extends StatefulWidget {
  const DataSyncPage({super.key});

  @override
  State<DataSyncPage> createState() => _DataSyncPageState();
}

class _DataSyncPageState extends State<DataSyncPage> {
  final DistributedChannel _distributedChannel = DistributedChannel();
  final TextEditingController _dataController = TextEditingController();
  String _syncResult = "";
  String _queriedData = "暂无同步数据";

  @override
  void initState() {
    super.initState();
    // 监听数据同步事件
    _listenDataSyncEvents();
    // 初始化时查询已有同步数据
    _querySyncData();
  }

  /// 监听数据同步事件
  void _listenDataSyncEvents() {
    _distributedChannel.dataSyncStream.listen(
      (message) {
        setState(() {
          _syncResult = message;
        });
        // 数据同步后,重新查询最新数据
        _querySyncData();
      },
      onError: (error) {
        setState(() {
          _syncResult = "数据同步错误:$error";
        });
      },
    );
  }

  /// 同步数据
  Future<void> _syncData() async {
    final data = _dataController.text.trim();
    if (data.isEmpty) {
      setState(() {
        _syncResult = "请输入要同步的数据";
      });
      return;
    }
    setState(() {
      _syncResult = "正在同步数据...";
    });
    try {
      final result = await _distributedChannel.syncData(data);
      if (result) {
        setState(() {
          _syncResult = "数据同步中,请等待...";
        });
      }
    } catch (e) {
      setState(() {
        _syncResult = "数据同步失败:$e";
      });
    }
  }

  /// 查询同步数据
  Future<void> _querySyncData() async {
    try {
      final data = await _distributedChannel.querySyncData();
      setState(() {
        _queriedData = data.isEmpty ? "暂无同步数据" : "最新同步数据:$data";
      });
    } catch (e) {
      setState(() {
        _queriedData = "查询数据失败:$e";
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("分布式数据同步"),
        backgroundColor: Colors.greenAccent,
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // 数据输入框
            TextField(
              controller: _dataController,
              decoration: const InputDecoration(
                labelText: "请输入要同步的数据",
                hintText: "例如:今天完成鸿蒙分布式能力集成",
                border: OutlineInputBorder(),
                contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: 12),
              ),
              maxLines: 3,
            ),
            const SizedBox(height: 20),
            // 同步按钮
            ElevatedButton(
              onPressed: _syncData,
              style: ElevatedButton.styleFrom(
                backgroundColor: Colors.green,
                padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
              ),
              child: const Text(
                "同步到所有设备",
                style: TextStyle(fontSize: 16, color: Colors.white),
              ),
            ),
            const SizedBox(height: 20),
            // 同步结果
            Text(
              "同步状态:$_syncResult",
              style: const TextStyle(fontSize: 14, color: Colors.grey[700]),
            ),
            const SizedBox(height: 30),
            // 查询结果
            const Text(
              "同步数据查询:",
              style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
            ),
            const SizedBox(height: 10),
            Container(
              padding: const EdgeInsets.all(16),
              decoration: BoxDecoration(
                border: Border.all(color: Colors.grey[300]!),
                borderRadius: BorderRadius.circular(8),
              ),
              child: Text(
                _queriedData,
                style: const TextStyle(fontSize: 15, color: Colors.black87),
              ),
            ),
            const SizedBox(height: 20),
            // 刷新数据按钮
            TextButton(
              onPressed: _querySyncData,
              child: const Text(
                "刷新最新数据",
                style: TextStyle(fontSize: 14, color: Colors.greenAccent),
              ),
            ),
          ],
        ),
      ),
    );
  }

  @override
  void dispose() {
    _dataController.dispose();
    super.dispose();
  }
}
3.3.2 测试效果
  1. 确保 2 个鸿蒙模拟器都已启动且已被发现;
  2. 在手机模拟器的 “分布式数据同步” 页面输入文本(如 “Hello 鸿蒙分布式能力!”),点击 “同步到所有设备”;
  3. 切换到平板模拟器的同一页面,点击 “刷新最新数据”,即可看到同步过来的文本;
  4. 反之,在平板模拟器输入数据同步,手机模拟器也能实时获取到最新数据。

3.4 实战 3:多设备协同任务清单(整合案例)

3.4.1 需求说明

构建一个简单的任务清单应用,支持:

  1. 多设备发现与连接;
  2. 在任意设备添加 / 删除任务,所有设备实时同步;
  3. 任务状态(已完成 / 未完成)跨设备同步。
3.4.2 核心代码实现(Flutter 端)

创建task_list_page.dart

dart

import 'package:flutter/material.dart';
import 'distributed_channel.dart';
import 'dart:convert';

// 任务模型
class Task {
  final String id;
  final String content;
  final bool isCompleted;

  Task({
    required this.id,
    required this.content,
    this.isCompleted = false,
  });

  // 转换为JSON字符串(用于同步)
  String toJson() {
    return jsonEncode({
      'id': id,
      'content': content,
      'isCompleted': isCompleted,
    });
  }

  // 从JSON字符串解析
  static Task fromJson(String jsonStr) {
    final Map<String, dynamic> json = jsonDecode(jsonStr);
    return Task(
      id: json['id'],
      content: json['content'],
      isCompleted: json['isCompleted'] ?? false,
    );
  }

  // 复制任务(用于修改状态)
  Task copyWith({bool? isCompleted}) {
    return Task(
      id: id,
      content: content,
      isCompleted: isCompleted ?? this.isCompleted,
    );
  }
}

class TaskListPage extends StatefulWidget {
  const TaskListPage({super.key});

  @override
  State<TaskListPage> createState() => _TaskListPageState();
}

class _TaskListPageState extends State<TaskListPage> {
  final DistributedChannel _distributedChannel = DistributedChannel();
  final TextEditingController _taskController = TextEditingController();
  List<Task> _taskList = [];
  List<Map<String, dynamic>> _connectedDevices = [];
  bool _isDiscovering = false;

  @override
  void initState() {
    super.initState();
    // 监听设备发现
    _listenDeviceDiscovery();
    // 监听数据同步(任务更新)
    _listenTaskSync();
    // 初始化查询任务
    _queryTasks();
  }

  /// 监听设备发现
  void _listenDeviceDiscovery() {
    _distributedChannel.deviceDiscoveryStream.listen(
      (device) {
        setState(() {
          if (!_connectedDevices.any((d) => d['deviceId'] == device['deviceId'])) {
            _connectedDevices.add(device);
          }
        });
      },
      onError: (error) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text("设备发现错误:$error")),
        );
      },
    );
  }

  /// 监听任务同步(所有设备的任务更新都会触发)
  void _listenTaskSync() {
    _distributedChannel.dataSyncStream.listen(
      (message) {
        if (message.contains("数据同步成功")) {
          // 解析同步的任务数据
          final jsonStr = message.split(':').last;
          _parseAndUpdateTasks(jsonStr);
        }
      },
      onError: (error) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text("任务同步错误:$error")),
        );
      },
    );
  }

  /// 解析同步的任务数据并更新列表
  void _parseAndUpdateTasks(String jsonStr) {
    try {
      final List<dynamic> jsonList = jsonDecode(jsonStr);
      final List<Task> newTasks = jsonList.map((json) => Task.fromJson(jsonEncode(json))).toList();
      setState(() {
        _taskList = newTasks;
      });
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text("任务已同步到所有设备")),
      );
    } catch (e) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text("任务解析失败:$e")),
      );
    }
  }

  /// 查询所有任务(从分布式网络)
  Future<void> _queryTasks() async {
    try {
      final data = await _distributedChannel.querySyncData();
      if (data.isNotEmpty) {
        _parseAndUpdateTasks(data);
      }
    } catch (e) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text("查询任务失败:$e")),
      );
    }
  }

  /// 添加任务
  Future<void> _addTask() async {
    final content = _taskController.text.trim();
    if (content.isEmpty) {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text("请输入任务内容")),
      );
      return;
    }
    // 创建新任务
    final newTask = Task(
      id: DateTime.now().millisecondsSinceEpoch.toString(),
      content: content,
    );
    final newTasks = [..._taskList, newTask];
    // 同步任务列表到分布式网络
    await _syncTasks(newTasks);
    // 清空输入框
    _taskController.clear();
  }

  /// 删除任务
  Future<void> _deleteTask(String taskId) async {
    final newTasks = _taskList.where((task) => task.id != taskId).toList();
    await _syncTasks(newTasks);
  }

  /// 切换任务完成状态
  Future<void> _toggleTaskCompleted(String taskId) async {
    final newTasks = _taskList.map((task) {
      if (task.id == taskId) {
        return task.copyWith(isCompleted: !task.isCompleted);
      }
      return task;
    }).toList();
    await _syncTasks(newTasks);
  }

  /// 同步任务列表到分布式网络
  Future<void> _syncTasks(List<Task> tasks) async {
    try {
      // 将任务列表转换为JSON字符串
      final jsonStr = jsonEncode(tasks.map((task) => jsonDecode(task.toJson())).toList());
      await _distributedChannel.syncData(jsonStr);
    } catch (e) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text("任务同步失败:$e")),
      );
    }
  }

  /// 切换设备发现
  Future<void> _toggleDeviceDiscovery() async {
    if (_isDiscovering) {
      await _distributedChannel.stopDeviceDiscovery();
      setState(() {
        _isDiscovering = false;
      });
    } else {
      setState(() {
        _connectedDevices.clear();
      });
      await _distributedChannel.startDeviceDiscovery();
      setState(() {
        _isDiscovering = true;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("分布式协同任务清单"),
        backgroundColor: Colors.purpleAccent,
        actions: [
          IconButton(
            icon: Icon(_isDiscovering ? Icons.stop : Icons.search),
            onPressed: _toggleDeviceDiscovery,
            tooltip: _isDiscovering ? "停止扫描设备" : "扫描设备",
          ),
          const SizedBox(width: 10),
        ],
      ),
      body: Column(
        children: [
          // 已连接设备提示
          if (_connectedDevices.isNotEmpty)
            Container(
              padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
              color: Colors.purple[100],
              child: Text(
                "已连接设备(${_connectedDevices.length}个):${_connectedDevices.map((d) => d['deviceName']).join('、')}",
                style: const TextStyle(fontSize: 12, color: Colors.purple[800]),
                overflow: TextOverflow.ellipsis,
              ),
            ),
          // 任务输入框
          Padding(
            padding: const EdgeInsets.all(16.0),
            child: Row(
              children: [
                Expanded(
                  child: TextField(
                    controller: _taskController,
                    decoration: const InputDecoration(
                      labelText: "添加新任务",
                      border: OutlineInputBorder(),
                      contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: 12),
                    ),
                  ),
                ),
                const SizedBox(width: 10),
                ElevatedButton(
                  onPressed: _addTask,
                  style: ElevatedButton.styleFrom(
                    backgroundColor: Colors.purpleAccent,
                    padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16),
                  ),
                  child: const Icon(Icons.add, color: Colors.white),
                ),
              ],
            ),
          ),
          // 任务列表
          Expanded(
            child: _taskList.isEmpty
                ? const Center(
                    child: Text(
                      "暂无任务\n添加任务后将同步到所有设备",
                      textAlign: TextAlign.center,
                      style: TextStyle(fontSize: 16, color: Colors.grey),
                    ),
                  )
                : ListView.builder(
                    itemCount: _taskList.length,
                    itemBuilder: (context, index) {
                      final task = _taskList[index];
                      return ListTile(
                        leading: Checkbox(
                          value: task.isCompleted,
                          onChanged: (value) => _toggleTaskCompleted(task.id),
                          activeColor: Colors.purpleAccent,
                        ),
                        title: Text(
                          task.content,
                          style: TextStyle(
                            decoration: task.isCompleted ? TextDecoration.lineThrough : null,
                            color: task.isCompleted ? Colors.grey : Colors.black87,
                          ),
                        ),
                        trailing: IconButton(
                          icon: const Icon(Icons.delete, color: Colors.red),
                          onPressed: () => _deleteTask(task.id),
                        ),
                      );
                    },
                  ),
          ),
        ],
      ),
    );
  }

  @override
  void dispose() {
    _taskController.dispose();
    super.dispose();
  }
}
3.4.3 测试效果
  1. 启动手机和平板 2 个模拟器;
  2. 在手机模拟器中扫描并连接平板设备;
  3. 在手机模拟器添加任务 “学习鸿蒙分布式能力”,平板模拟器实时显示该任务;
  4. 在平板模拟器将任务标记为 “已完成”,手机模拟器的任务状态同步更新;
  5. 在手机模拟器删除该任务,平板模拟器的任务也被删除。

四、常见问题与解决方案

4.1 设备发现失败

问题现象 可能原因 解决方案
调用startDeviceDiscovery返回失败 未添加DISTRIBUTED_DEVICE_DISCOVER权限 config.json中添加该权限,参考 2.3.3 节
模拟器之间无法发现 模拟器网络不互通 确保所有模拟器使用同一网络(默认的 “HarmonyOS Emulator Network”)
错误码 1001(权限被拒绝) 动态权限未申请 鸿蒙 API 9 + 部分权限需要动态申请,在原生端添加权限申请代码:requestPermissions(new String[]{"ohos.permission.DISTRIBUTED_DEVICE_DISCOVER"}, 100);

4.2 数据同步失败

问题现象 可能原因 解决方案
数据同步后其他设备无法获取 未注册数据监听 确保所有设备都调用了querySyncData查询最新数据,或监听dataSyncStream事件
错误码 2002(数据格式错误) 同步的数据不是字节数组 确保将数据转换为byte[]后再调用putData,参考 3.1.1 节的syncData方法
数据同步延迟 网络不稳定 优先使用 Wi-Fi 网络,避免蓝牙传输大文件;可添加数据同步重试机制

4.3 Flutter 与原生通信失败

问题现象 可能原因 解决方案
MethodChannel 调用返回notImplemented 方法名不一致 确保 Flutter 端和原生端的方法名(如startDeviceDiscovery)完全一致
EventChannel 无回调 未保存EventSink对象 检查原生端onListen方法是否正确赋值deviceEventSinkdataEventSink
数据解析失败 JSON 格式错误 推荐使用dart:convert和原生端的Gson进行 JSON 序列化 / 反序列化,避免手动拼接 JSON 字符串

4.4 其他常见问题

  1. Flutter 模块编译失败:确保 Flutter SDK 版本≥3.10,执行flutter clean后重新同步项目;
  2. 鸿蒙原生 API 找不到:检查build.gradle中是否添加了分布式能力依赖(distributeddevicedistributeddb);
  3. 模拟器启动失败:确保电脑配置满足要求(至少 8GB 内存),更新 DevEco Studio 到最新版本。

五、总结与展望

5.1 本文核心总结

本文详细讲解了 Flutter 接入鸿蒙分布式能力的完整流程,核心要点包括:

  1. 通信桥梁:通过MethodChannelEventChannel实现 Flutter 与鸿蒙原生的双向通信;
  2. 核心能力:设备发现(DistributedDeviceManager)、数据同步(DistributedDataManager)的 API 调用与封装;
  3. 实战案例:从单一能力测试到完整的协同任务清单,覆盖多设备协同的核心场景;
  4. 问题排查:针对设备发现、数据同步、通信失败等常见问题提供解决方案。

通过以上步骤,开发者可以快速将鸿蒙分布式能力集成到 Flutter 项目中,构建跨终端协同应用。

5.2 进阶拓展方向

  1. 分布式任务调度:将应用的耗时任务(如文件压缩、视频解码)分发到性能更强的设备执行;
  2. 分布式文件传输:基于分布式软总线实现大文件(如图片、视频)的跨设备高速传输;
  3. 多设备 UI 协同:实现 “手机投屏到平板”“手表控制手机 UI” 等更复杂的协同场景;
  4. 数据加密同步:对敏感数据(如用户信息)进行加密后再同步,提升安全性。

5.3 参考资料

随着鸿蒙生态的不断完善,Flutter 与鸿蒙分布式能力的结合将催生更多创新应用场景。如果你在开发过程中遇到新的问题或有更好的实践方案,欢迎在评论区交流分享!

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐