大文件千万别走 DDO

在截图整理工具的分享模块里,我想实现一个“把截图瞬间同步到平板”的功能。因为之前做状态同步用过分布式数据对象(DDO),觉得还挺好用,就顺手把图片转成了 Uint8Array 塞进 DDO 的字段里。

结果两台设备一碰,手机端直接闪退,或者平板上一直转圈卡死。我查日志发现,底层发生了严重的 OOM 以及序列化异常。

分布式数据对象是为了“状态”同步设计的,比如购物车的勾选状态、表单的输入进度。它的设计初衷是轻量级、结构化数据的高效流转。底层走的是软总线的状态同步协议,对单条数据的载荷大小极其敏感。把几兆的图片二进制丢进去,等于让自行车去拉集装箱,不仅拉不动,车轴还得断。

文件分享用分布式文件系统

如果是传截图文件,正确的解法是使用分布式文件系统的文件共享能力,或者通过 abilityConnectionManager 建立一条数据通道直接传流。

typescript

import { distributedFile } from '@kit.DistributedServiceKit';

async function shareScreenshotToDevice(localUri: string, targetDeviceId: string) {
  try {
    // 打开本地文件
    const file = await distributedFile.open(localUri, distributedFile.OpenMode.READ_ONLY);
    
    // 构建发送描述
    const sendOption: distributedFile.SendOption = {
      targetDeviceId: targetDeviceId,
      // 传输文件数据
    };
    
    // 将文件挂载到分布式网络上,对方通过 URI 即可访问
    const remoteUri = await distributedFile.sendFile(file, sendOption);
    return remoteUri;
  } catch (error) {
    console.error(`文件跨端分享失败: ${JSON.stringify(error)}`);
  }
}

sendFile 是系统级的传输接口,它支持断点续传、分片发送,而且是在独立的后台线程通道里跑的。平板侧会收到一个 remoteUri,直接通过这个 Uri 就能渲染图片,不需要把整个文件全量下载到内存里。

跨端通信的选型矩阵

在鸿蒙生态里做跨端,开发者脑子里得有一张选型表。状态同步(比如设置页的开关),用 distributedDataObject,简单无脑;结构化指令(比如点播控制),用 rpc 或者 want 拉起;如果是视频、大图、数据库备份,老老实实用分布式文件或者 fileIo 配合 stream 传输。

选错了通道,轻则代码越写越复杂,重则导致应用内存崩溃。只有把数据的“重量”和“生命周期”掂量清楚,跨端交互才能丝滑稳定。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐