鸿蒙ACE-V2状态分析@AppStorageV2

186 阅读2分钟

AppStorageV2: 应用全局UI状态存储

developer.huawei.com/consumer/cn…

AppStorageV2是在应用UI启动时会被创建的单例。它的目的是为了提供应用状态数据的中心存储,这些状态数据在应用级别都是可访问的。AppStorageV2将在应用运行过程保留其数据。数据通过唯一的键字符串值访问

转换前

/**
 *
 * AppStorageV2Cmp.ets
 * Created by unravel on 2024/8/2
 * @abstract
 */

import { router, AppStorageV2 } from '@kit.ArkUI';

// 数据中心
@ObservedV2
export class Sample {
  @Trace p1: number = 0;
  p2: number = 10;
}

@ComponentV2
export struct AppStorageV2Cmp {
  // 在AppStorageV2中创建一个key为Sample的键值对(如果存在,则返回AppStorageV2中的数据),并且和prop关联
  @Local prop: Sample = AppStorageV2.connect(Sample, () => new Sample())!;

  build() {
    Column() {
      Button('Go to page2')
        .onClick(() => {
          router.pushUrl({
            url: 'pages/Page2'
          })
        })

      Button('Page1 connect the key Sample')
        .onClick(() => {
          // 在AppStorageV2中创建一个key为Sample的键值对(如果存在,则返回AppStorageV2中的数据),并且和prop关联
          this.prop = AppStorageV2.connect(Sample, 'Sample', () => new Sample())!;
        })

      Button('Page1 remove the key Sample')
        .onClick(() => {
          // 从AppStorageV2中删除后,prop将不会再与key为Sample的值关联
          AppStorageV2.remove(Sample);
        })

      Text(`Page1 add 1 to prop.p1: ${this.prop.p1}`)
        .fontSize(30)
        .onClick(() => {
          this.prop.p1++;
        })

      Text(`Page1 add 1 to prop.p2: ${this.prop.p2}`)
        .fontSize(30)
        .onClick(() => {
          // 页面不刷新,但是p2的值改变了
          this.prop.p2++;
        })

      // 获取当前AppStorageV2里面的所有key
      Text(`all keys in AppStorage: ${AppStorageV2.keys()}`)
        .fontSize(30)
    }
  }
}

转换后

if (!("finalizeConstruction" in ViewPU.prototype)) {
    Reflect.set(ViewPU.prototype, "finalizeConstruction", () => { });
}
import router from "@ohos:router";
import { AppStorageV2 } from "@ohos:arkui.StateManagement";
// 数据中心
@ObservedV2
export class Sample {
    @Trace
    p1: number = 0;
    p2: number = 10;
}
export class AppStorageV2Cmp extends ViewV2 {
    constructor(parent, params, __localStorage, elmtId = -1, paramsLambda, extraInfo) {
        super(parent, elmtId, extraInfo);
        this.prop = AppStorageV2.connect(Sample, () => new Sample())!;
        this.finalizeConstruction();
    }
    // 在AppStorageV2中创建一个key为Sample的键值对(如果存在,则返回AppStorageV2中的数据),并且和prop关联
    @Local
    prop: Sample;
    initialRender() {
        this.observeComponentCreation2((elmtId, isInitialRender) => {
            Column.create();
        }, Column);
        this.observeComponentCreation2((elmtId, isInitialRender) => {
            Button.createWithLabel('Go to page2');
            Button.onClick(() => {
                router.pushUrl({
                    url: 'pages/Page2'
                });
            });
        }, Button);
        Button.pop();
        this.observeComponentCreation2((elmtId, isInitialRender) => {
            Button.createWithLabel('Page1 connect the key Sample');
            Button.onClick(() => {
                // 在AppStorageV2中创建一个key为Sample的键值对(如果存在,则返回AppStorageV2中的数据),并且和prop关联
                this.prop = AppStorageV2.connect(Sample, 'Sample', () => new Sample())!;
            });
        }, Button);
        Button.pop();
        this.observeComponentCreation2((elmtId, isInitialRender) => {
            Button.createWithLabel('Page1 remove the key Sample');
            Button.onClick(() => {
                // 从AppStorageV2中删除后,prop将不会再与key为Sample的值关联
                AppStorageV2.remove(Sample);
            });
        }, Button);
        Button.pop();
        this.observeComponentCreation2((elmtId, isInitialRender) => {
            Text.create(`Page1 add 1 to prop.p1: ${this.prop.p1}`);
            Text.fontSize(30);
            Text.onClick(() => {
                this.prop.p1++;
            });
        }, Text);
        Text.pop();
        this.observeComponentCreation2((elmtId, isInitialRender) => {
            Text.create(`Page1 add 1 to prop.p2: ${this.prop.p2}`);
            Text.fontSize(30);
            Text.onClick(() => {
                // 页面不刷新,但是p2的值改变了
                this.prop.p2++;
            });
        }, Text);
        Text.pop();
        this.observeComponentCreation2((elmtId, isInitialRender) => {
            // 获取当前AppStorageV2里面的所有key
            Text.create(`all keys in AppStorage: ${AppStorageV2.keys()}`);
            // 获取当前AppStorageV2里面的所有key
            Text.fontSize(30);
        }, Text);
        // 获取当前AppStorageV2里面的所有key
        Text.pop();
        Column.pop();
    }
    rerender() {
        this.updateDirtyElements();
    }
}

AppStorageV2 类

AppStorageV2.appStorageV2Impl_ = AppStorageV2Impl.instance();

image.png

class AppStorageV2Impl extends StorageHelper

image.png

public connect(type: TypeConstructorWithArgs, keyOrDefaultCreator?: string | StorageDefaultCreator, defaultCreator?: StorageDefaultCreator): T | undefined

image.png

从这里我们也看出,存储的实际上是一个对象的引用,然后App内多个页面之所以能够同步是因为他们访问的是同一个对象

AppStorageV2本身没有观察数据的变化,实际驱动UI刷新的动作还需要数据自身来完成,即对应的class必须使用ObservedV2和Trace装饰