【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裝飾的類(支持子線程傳遞)
class UserInfo {userId: number = 0;username: string = 'Guest';score: number = 0;isOnline: boolean = false;// 構造函數初始化數據constructor(userId: number, username: string) {this.userId = userId;this.username = username;}
}// 子線程任務:模擬數據處理(如網絡請求/復雜計算)
function processDataInThread(userId: number): UserInfo {// 模擬耗時操作(子線程執行)let result = new UserInfo(userId, 'Loading...');setTimeout(() => {// 模擬數據更新result.score = Math.floor(Math.random() * 100);result.isOnline = true;}, 1000);return result;
}
struct SendableMakeObservedDemo {// 主線程可觀察數據:通過makeObserved包裝@Sendable對象 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;
}
struct JsonMakeObservedDemo {// 原始 JSON 字符串private rawJson: string = '{"name": "Alice", "age": 25, "email": "alice@example.com"}';// 使用 makeObserved 包裝 JSON.parse 返回的對象 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);})}}
}
三、注意
-
getTarget問題:
通過getTarget獲取原始對象后修改屬性,不會觸發UI刷新(需操作代理對象) -
兼容性錯誤:
與@State等V1裝飾器混用會拋異常,需使用V2裝飾器(@Local/@Provide等)