写点什么

【HarmonyOS 5】makeObserved 接口详解

作者:GeorgeGcs
  • 2025-04-21
    上海
  • 本文字数:2534 字

    阅读完需:约 8 分钟

【HarmonyOS 5】makeObserved接口详解

【HarmonyOS 5】makeObserved 接口详解

一、makeObserved 接口是什么?

makeObserved 接口(API version 12 起可用)用于将非观察数据转为可观察数据,适用于三方包类、@Sendable 装饰的类、JSON.parse 返回的对象、collections.Array/Set/Map 等场景。


不支持 undefined 和 null 类型。以及 V1 状态装饰器(@State/@Prop)及已被观察的数据,避免双重代理。主要处理的是 Object 类型,非 Object 类型,例如基本数据类型 number 这种,都不支持。


需要注意的是,makeObserved 主要针对的是 V2 的使用场景。因为它是为了解决 @Trace/@ObservedV2 无法覆盖的痛点观察需求。比如从网络请求返回的 JSON 对象,需要在 UI 上进行观测操作。就可使用 makeObserved。所以 V1 使用 @State 就可解决的问题,不用考虑这个。

二、makeObserved 如何使用?

(1)接口调用使用及其简单,只需要导入 import { UIUtils } from '@kit.ArkUI'进行接口调用接口。麻烦的是识别你的入参是否支持观测监听。


import { UIUtils } from '@kit.ArkUI';

class UserInfo { id: number = 0;}let observedInfo: UserInfo = UIUtils.makeObserved(new UserInfo());
复制代码


(2)可从操作的业务场景进行区分,符合以下三种场景一般可操作:1、三方 SDK 包中的数据类,这种情况下需要 UI 可监测,因为无法手动添加 @Trace,一般可支持。【该场景较为简单,参考上面示例即可】


2、@Sendable 装饰的类,因为禁止动态修改属性,一般可支持。


import { taskpool } from '@kit.ArkTS';import { UIUtils } from '@kit.ArkUI';
// 定义@Sendable装饰的类(支持子线程传递)@Sendableclass UserInfo { userId: number = 0; username: string = 'Guest'; score: number = 0; isOnline: boolean = false;
// 构造函数初始化数据 constructor(userId: number, username: string) { this.userId = userId; this.username = username; }}
// 子线程任务:模拟数据处理(如网络请求/复杂计算)@Concurrentfunction processDataInThread(userId: number): UserInfo { // 模拟耗时操作(子线程执行) let result = new UserInfo(userId, 'Loading...'); setTimeout(() => { // 模拟数据更新 result.score = Math.floor(Math.random() * 100); result.isOnline = true; }, 1000); return result;}
@Entry@ComponentV2struct SendableMakeObservedDemo { // 主线程可观察数据:通过makeObserved包装@Sendable对象 @Local observedUser: UserInfo = UIUtils.makeObserved(new UserInfo(-1, '未登录'));
build() { Column({ space: 20 }) .width('100%') .padding(30) { Text('@Sendable + makeObserved 演示') .fontSize(24) .fontWeight(500) // 显示用户信息 Text(`用户ID: ${this.observedUser.userId}`) .fontSize(18) Text(`用户名: ${this.observedUser.username}`) .fontSize(18) Text(`分数: ${this.observedUser.score}`) .fontSize(18) Text(`在线状态: ${this.observedUser.isOnline ? '在线' : '离线'}`) .fontSize(18) // 触发子线程任务的按钮 Button('加载用户数据(子线程处理)') .onClick(() => { // 在子线程执行数据处理 taskpool.execute(processDataInThread, 1001).then((user: UserInfo) => { // 子线程返回的@Sendable对象在主线程重新包装为可观察数据 this.observedUser = UIUtils.makeObserved(user); }); }) // 本地修改数据的按钮(演示可观察性) Button('本地增加分数') .onClick(() => { this.observedUser.score += 10; // 直接修改属性,触发UI刷新 }) } }}
复制代码


3、 JSON.parse 返回的匿名对象,一般是网络请求反馈,一般可支持。


import { UIUtils } from '@kit.ArkUI';import { JSON } from '@kit.ArkTS';
// 定义 JSON 数据结构(示例接口)interface UserData { name: string; age: number; email: string;}
@Entry@ComponentV2struct JsonMakeObservedDemo { // 原始 JSON 字符串 private rawJson: string = '{"name": "Alice", "age": 25, "email": "alice@example.com"}'; // 使用 makeObserved 包装 JSON.parse 返回的对象 @Local observedData: UserData = UIUtils.makeObserved(JSON.parse(this.rawJson) as UserData);
build() { Column({ space: 30 }) .width('100%') .padding(30) { // 显示 JSON 数据 Text('JSON 可观察数据演示') .fontSize(24) .fontWeight(500) Text(`姓名: ${this.observedData.name}`) .fontSize(18) Text(`年龄: ${this.observedData.age}`) .fontSize(18) Text(`邮箱: ${this.observedData.email}`) .fontSize(18) // 修改姓名的按钮 Button('修改姓名为 "Bob"') .onClick(() => { this.observedData.name = 'Bob'; // 直接修改属性,触发 UI 刷新 }) // 修改年龄的按钮 Button('年龄 +1') .onClick(() => { this.observedData.age++; // 数值类型修改,触发 UI 刷新 }) // 重置为原始数据的按钮 Button('重置数据') .onClick(() => { // 重新解析 JSON 并包装为可观察数据 this.observedData = UIUtils.makeObserved(JSON.parse(this.rawJson) as UserData); }) } }}
复制代码

三、注意

  1. getTarget 问题:通过 getTarget 获取原始对象后修改属性,不会触发 UI 刷新(需操作代理对象)

  2. 兼容性错误:与 @State 等 V1 装饰器混用会抛异常,需使用 V2 装饰器(@Local/@Provide 等)

发布于: 刚刚阅读数: 6
用户头像

GeorgeGcs

关注

路漫漫其修远兮,吾将上下而求索。 2024-12-24 加入

历经腾讯,宝马,研究所,金融。 待过私企,外企,央企。 深耕大应用开发领域十年。 OpenHarmony,HarmonyOS,Flutter,H5,Android,IOS。 目前任职鸿蒙应用架构师。 HarmonyOS官方认证创作先锋,华为开发专家HDE。

评论

发布
暂无评论
【HarmonyOS 5】makeObserved接口详解_GeorgeGcs_InfoQ写作社区