HarmonyOS鸿蒙Next中在Router的传递数据的过程中,如何封装自定义的对象传递到另外一个页面?

HarmonyOS鸿蒙Next中在Router的传递数据的过程中,如何封装自定义的对象传递到另外一个页面?

4 回复

使用ArkTS(一种为鸿蒙系统设计的TypeScript超集)进行页面间数据传递时,过程与在普通 TypeScript 环境或Android原生开发中类似。在鸿蒙系统中,页面之间的导航和数据传递通常通过Ability(能力)和Intent来实现。以下是在鸿蒙开发中,使用ArkTS封装自定义对象并传递到另一个页面的步骤:

  1. 定义自定义对象:

首先,你需要定义一个自定义的TypeScript类(在ArkTS环境中),这个类将包含你想要传递的数据。

export class User {
  id: number;
  name: string;
  email: string;
  constructor(id: number, name: string, email: string) {
    this.id = id;
    this.name = name;
    this.email = email;
  }
}
  1. 通过Router传递参数

更多关于HarmonyOS鸿蒙Next中在Router的传递数据的过程中,如何封装自定义的对象传递到另外一个页面?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


【背景知识】

  • @ohos.router (页面路由)页面跳转并传递参数的四种方式:

    • router.pushUrl,通过页面Url方式实现页面推送跳转,将指定页面页面推送至路由栈顶层渲染显示;
    • router.replaceUrl,通过页面Url方式实现页面替换跳转,将当前顶层页面替换成指定页面渲染显示;
    • router.pushNamedRoute,通过页面名字实现页面跳转,将指定页面页面推送至路由栈顶层渲染显示;
    • router.replaceNamedRoute,通过页面名字实现页面跳转,将当前顶层页面替换成指定页面渲染显示。
  • 参数形式:

    • 其中router.pushUrl与router.replaceUrl描述页面信息的参数为RouterOptions,传递参数结构形式为:

      {
        url: 'XXX/XXX/XXX', // 传递的方式,必填参数
        params: Object, // 传递的数据,必填参数,可以是基础类型或者自定义数据类型
        recoverable: true // 页面是否可恢复,该参数为非必填参数,默认为true
      }
      
    • router.pushNamedRoute与router.replaceNamedRoute描述页面信息的参数为NamedRouterOptions,传递参数结构形式为:

      {
        name: 'XXX', // 传递的方式,必填参数
        params: Object, // 传递的数据,必填参数,可以是基础类型或者自定义数据类型
        recoverable: true // 页面是否可恢复,该参数为非必填参数,默认为true
      }
      

注意事项:params不支持传递方法和系统返回的对象。

【解决方案】

定义一个自定义的TypeScript类

// 示例:对象传参
// 封装自定义的对象
class Person {
  name: string = '';
  info: Info = {}
}

class Info {
  age?: number = 0
}

router.pushUrl({
  url: 'pages/Second',
  params: {
    name: "Welcome",
    info: {
      age: 20
    }
  }
})

除传参外,需要确认获取参数的方式:router.getParams。获取的参数数据结构和传递的参数一致。

接收router传递的参数方案:

// 建议使用this.getUIContext().getRouter().getParams()
@State params: ParamInfo = router.getParams() as ParamInfo

aboutToAppear(): void {
  // 方案一
  let params = (router.getParams() as Record<string, object>)
  let name = params["name"]
  let info = params["info"]
  console.log("方案一:" + JSON.stringify(params) + " name:" + name + " info:" + info)

  // 方案二
  let params2: object = Object(router.getParams())
  console.log("方案二:" + JSON.stringify(params2) + " name:" + params2["name"] + " info:" + params2["info"])

  // 方案三
  let paramInfo: ParamInfo = router.getParams() as ParamInfo
  console.log("方案三:" + JSON.stringify(paramInfo) + " name:" + paramInfo.name + " info:" + paramInfo.info.age)
}
方案 优点 缺点 应用场景
方案一:转成Record 无须定义数据类 遇到嵌套类型数据处理麻烦 适用于只有基本类型场景
方案二:转成Object 无须定义数据类 遇到嵌套类型数据处理麻烦 适用于只有基本类型场景
方案三:转成特定的类 嵌套类型数据处理简单 需要事先定义好数据类 适用于嵌套数据类型场景

【常见FAQ】

Q:params是否支持抽象类的传递? A:不支持,复杂的页面传参建议使用Navigation。

Q:params传递HashMap类型数据,目标页面无法获取到内容如何解决? A:router传递的参数会经过序列化,过程中会丢失方法。所以无法使用map,list传参。建议使用Navigation。

在HarmonyOS Next中使用Router传递自定义对象:

  1. 自定义类需实现Parcelable接口并重写marshalling/unmarshalling方法进行序列化

  2. 发送页面:

let parcelableData = new MyParcelableClass()
router.pushUrl({
  url: 'pages/TargetPage',
  params: { obj: parcelableData }
})
  1. 接收页面通过router.getParams()获取:
let receivedData = router.getParams()?.['obj'] as MyParcelableClass

注意传递的Parcelable对象大小限制为1MB。

在HarmonyOS Next中通过Router传递自定义对象,需要先将对象序列化为可传递的数据格式。以下是具体实现方法:

  1. 使用Parcelable接口序列化对象:
public class MyData implements Parcelable {
    private String name;
    private int age;

    // 实现Parcelable接口方法
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(name);
        dest.writeInt(age);
    }

    // 添加CREATOR
    public static final Creator<MyData> CREATOR = new Creator<MyData>() {
        @Override
        public MyData createFromParcel(Parcel in) {
            return new MyData(in);
        }
    };
}
  1. 传递对象:
// 发送方
Router router = Router.getInstance();
router.addParams("key", new MyParcelableData());
router.push(RouterPagePath.TARGET_PAGE);

// 接收方
MyData data = (MyData) getIntent().getParcelableExtra("key");
  1. 对于复杂对象,也可以使用JSON序列化:
// 发送方
Gson gson = new Gson();
String jsonData = gson.toJson(myObject);
router.addParams("key", jsonData);

// 接收方
String json = getIntent().getStringExtra("key");
MyObject obj = gson.fromJson(json, MyObject.class);

注意事项:

  • 确保自定义类实现Parcelable接口
  • 数据大小不超过1MB限制
  • 复杂对象建议使用JSON序列化方式
回到顶部