ArkUI数据更新场景

当需要网络下载或者本地生成的数据需要发送到UI线程进行展示时,由于ArkUI的标注和@Sendable装饰器不能同时修饰变量和对象,因此需要使用makeObserved在ArkUI中导入可观测的Sendable共享数据。

本示例说明以下场景:

  • makeObserved在传入@Sendable类型的数据后有观测能力,且其变化可以触发UI更新。
  • 从子线程获取数据,整体替换UI线程的可观测数据。
  • 从子线程获取的数据重新执行makeObserved,变为可观测数据。
  • 将数据从UI主线程传递回子线程时,只传递不可观测的数据。makeObserved的返回值不能直接传给子线程。
@Sendable
export class SendableData {
  public name: string = 'Tom';
  public age: number = 20;
  public gender: number = 1;
  public likes: number = 1;
  public follow: boolean = false;
}
import { taskpool } from '@kit.ArkTS';
import { SendableData } from './SendableData';
import { UIUtils } from '@kit.ArkUI';

@Concurrent
function threadGetData(param: string): SendableData {
  // 在子线程处理数据
  let ret = new SendableData();
  console.info(`Concurrent threadGetData, param ${param}`);
  ret.name = param + '-o';
  ret.age = Math.floor(Math.random() * 40);
  ret.likes = Math.floor(Math.random() * 100);
  return ret;
}

@Entry
@ComponentV2
struct Index {
  // 通过makeObserved给普通对象或是Sendable对象添加可观测能力
  @Local send: SendableData = UIUtils.makeObserved(new SendableData());

  build() {
    Column() {
      Text(this.send.name)
      Button('change name').onClick(() => {
        // 可以观察到属性的改变
        this.send.name += '0';
      })
        .id('change name')
      Button('task').onClick(() => {
        // 将待执行的函数放入taskpool内部任务队列等待,等待分发到工作线程执行。
        // 因为数据的构建和处理可以在子线程中完成,但有观测能力的数据不能传给子线程,只有在UI主线程里才可以操作可观测的数据。
        // 所以这里只是将`this.send`的属性`name`传给子线程操作。
        taskpool.execute(threadGetData, this.send.name).then(val => {
          // 和@Local一起使用,可以观察this.send的变化
          this.send = UIUtils.makeObserved(val as SendableData);
        })
      })
        .id('task')
    }
  }
}