问题场景描述

在鸿蒙应用开发中,我们经常遇到这样的问题:从Page A跳转到Page B时,通过router.pushUrl()传递的复杂对象数据在页面间丢失或解析失败。特别是在传递自定义类对象或大数据量时,这个问题尤为突出。

根本原因分析

  1. 序列化限制:鸿蒙的页面路由只支持基本数据类型和可序列化的简单对象
  2. 数据大小限制:单次传递数据超过100KB时可能出现截断
  3. 生命周期差异:页面跳转时原页面的数据可能已被回收

解决方案一:使用全局数据总线

// 1. 创建全局数据管理器
class DataBus {
  private static instance: DataBus;
  private dataMap: Map<string, Object> = new Map();

  public static getInstance(): DataBus {
    if (!DataBus.instance) {
      DataBus.instance = new DataBus();
    }
    return DataBus.instance;
  }

  public setData(key: string, data: Object): void {
    this.dataMap.set(key, data);
  }

  public getData(key: string): Object | undefined {
    return this.dataMap.get(key);
  }
}

// 2. 在Page A设置数据
DataBus.getInstance().setData('userInfo', {
  name: '张三',
  age: 28,
  avatar: 'base64...'
});

// 3. 在Page B获取数据
let user = DataBus.getInstance().getData('userInfo');

解决方案二:使用持久化存储

// 1. 使用Preferences存储
import preferences from '@ohos.data.preferences';

async function saveData(context) {
  try {
    let pref = await preferences.getPreferences(context, 'mydata');
    await pref.put('complexObj', JSON.stringify(complexData));
    await pref.flush();
  } catch (e) {
    console.error(`保存失败: ${e}`);
  }
}

// 2. 在目标页面读取
async function loadData(context) {
  let pref = await preferences.getPreferences(context, 'mydata');
  let dataStr = await pref.get('complexObj', 'default');
  return JSON.parse(dataStr);
}

解决方案三:优化路由传参方式

// 1. 将复杂对象转换为字符串
let params = {
  id: 123,
  data: encodeURIComponent(JSON.stringify(complexData))
};

// 2. 通过URL传递
router.pushUrl({
  url: 'pages/PageB',
  params: params
});

// 3. 在Page B解析
onPageShow() {
  let uri = router.getParams();
  let complexData = JSON.parse(decodeURIComponent(uri.data));
}

性能对比

方案 优点 缺点 适用场景
全局数据总线 内存访问快 应用重启会丢失 单次会话内的数据共享
持久化存储 数据可保留 IO操作有延迟 需要持久化的数据
URL传参 无需额外存储 有大小限制 简单数据传递

最佳实践建议

  1. 对于小于50KB的数据,优先使用方案三(URL传参)
  2. 对于频繁访问的中间数据,使用方案一(全局数据总线)
  3. 对于需要持久化的数据,使用方案二(Preferences)
  4. 大数据量(>100KB)考虑使用分布式数据对象

常见问题排查

  1. 数据格式错误:确保所有自定义类都实现了序列化接口
  2. 内存泄漏:全局数据总线中的数据要及时清理
  3. 编码问题:URL传参时注意encode/decode的对称使用

扩展思考

对于跨设备数据共享,可以结合鸿蒙的分布式能力:

// 创建分布式数据对象
import distributedObject from '@ohos.data.distributedDataObject';
let g_object = distributedObject.createDistributedObject({data: null});

// 设置数据
g_object.data = complexData;
g_object.setSessionId('default');
Logo

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

更多推荐