鸿蒙ACE-V1状态分析@Provide、@Consume

@Provide装饰器和@Consume装饰器:与后代组件双向同步

developer.huawei.com/consumer/cn…

@Provide初始化规则图示

@Consume初始化规则图示

框架行为

  1. 初始渲染:

    1. @Provide装饰的变量会以map的形式,传递给当前@Provide所属组件的所有子组件
    2. 子组件中如果使用@Consume变量,则会在map中查找是否有该变量名/alias(别名)对应的@Provide的变量,如果查找不到,框架会抛出JS ERROR;
    3. 在初始化@Consume变量时,和@State/@Link的流程类似,@Consume变量会保存 在map中查找到的@Provide变量,并把自己注册给@Provide。
  2. 当@Provide装饰的数据变化时:

    1. 通过初始渲染的步骤可知,子组件@Consume已把自己注册给父组件。父组件@Provide变量变更后,会遍历更新所有依赖它的系统组件(elementid)和状态变量(@Consume);
    2. 通知@Consume更新后,子组件所有依赖@Consume的系统组件(elementId)都会被通知更新。以此实现@Provide对@Consume状态数据同步。
  3. 当@Consume装饰的数据变化时:

    通过初始渲染的步骤可知,子组件@Consume持有@Provide的实例。在@Consume更新后调用@Provide的更新方法,将更新的数值同步回@Provide,以此实现@Consume向@Provide的同步更新。

转换前代码


import { StateClass, StateInterface } from './StateDemoPage'
 
@Component
export struct ConsumeChildCmpt {
  
  @Consume provideSimpleState: number
  
  @Consume provideClassState: StateClass
  
  @Consume provideInterfaceState: StateInterface
  
  @Consume provideArrayState: StateClass[]
  
  @Consume provideDateState: Date
  
  @Consume provideMapState: Map<number, string>
  
  @Consume provideSetState: Set<number>
  
  @Consume provideUnionState: number | undefined
 
  build() {
    Column() {
      Text(`@Consume provideSimpleState: ${this.provideSimpleState}`)
      Text(`@Consume provideClassState: ${this.provideClassState.value}`)
      Text(`@Consume provideInterfaceState: ${this.provideInterfaceState.value}`)
      Text(`@Consume provideArrayState: ${this.provideArrayState.map(item => item.value).join(',')}`)
      Text(`@Consume provideDateState: ${this.provideDateState}`)
      Text(`@Consume provideMapState: ${Array.from(this.provideMapState)
        .map((kv: [number, string]) => `${kv[0]}:${kv[1]}`)
        .join(',')}`)
      Text(`@Consume provideSetState: ${Array.from(this.provideSetState).join(',')}`)
      Text(`@Consume provideUnionState: ${this.provideUnionState}`)
    }
  }
}

转换后代码

if (!("finalizeConstruction" in ViewPU.prototype)) {
    Reflect.set(ViewPU.prototype, "finalizeConstruction", () => { });
}
interface ConsumeChildCmpt_Params {
    provideSimpleState?: number;
    provideClassState?: StateClass;
    provideInterfaceState?: StateInterface;
    provideArrayState?: StateClass[];
    provideDateState?: Date;
    provideMapState?: Map;
    provideSetState?: Set;
    provideUnionState?: number | undefined;
}
import type { StateClass, StateInterface } from './StateDemoPage';
export class ConsumeChildCmpt extends ViewPU {
    constructor(parent, params, __localStorage, elmtId = -1, paramsLambda = undefined, extraInfo) {
        super(parent, __localStorage, elmtId, extraInfo);
        if (typeof paramsLambda === "function") {
            this.paramsGenerator_ = paramsLambda;
        }
        this.__provideSimpleState = this.initializeConsume("provideSimpleState", "provideSimpleState");
        this.__provideClassState = this.initializeConsume("provideClassState", "provideClassState");
        this.__provideInterfaceState = this.initializeConsume("provideInterfaceState", "provideInterfaceState");
        this.__provideArrayState = this.initializeConsume("provideArrayState", "provideArrayState");
        this.__provideDateState = this.initializeConsume("provideDateState", "provideDateState");
        this.__provideMapState = this.initializeConsume("provideMapState", "provideMapState");
        this.__provideSetState = this.initializeConsume("provideSetState", "provideSetState");
        this.__provideUnionState = this.initializeConsume("provideUnionState", "provideUnionState");
        this.setInitiallyProvidedValue(params);
        this.finalizeConstruction();
    }
    setInitiallyProvidedValue(params: ConsumeChildCmpt_Params) {
    }
    updateStateVars(params: ConsumeChildCmpt_Params) {
    }
    purgeVariableDependenciesOnElmtId(rmElmtId) {
        this.__provideSimpleState.purgeDependencyOnElmtId(rmElmtId);
        this.__provideClassState.purgeDependencyOnElmtId(rmElmtId);
        this.__provideInterfaceState.purgeDependencyOnElmtId(rmElmtId);
        this.__provideArrayState.purgeDependencyOnElmtId(rmElmtId);
        this.__provideDateState.purgeDependencyOnElmtId(rmElmtId);
        this.__provideMapState.purgeDependencyOnElmtId(rmElmtId);
        this.__provideSetState.purgeDependencyOnElmtId(rmElmtId);
        this.__provideUnionState.purgeDependencyOnElmtId(rmElmtId);
    }
    aboutToBeDeleted() {
        this.__provideSimpleState.aboutToBeDeleted();
        this.__provideClassState.aboutToBeDeleted();
        this.__provideInterfaceState.aboutToBeDeleted();
        this.__provideArrayState.aboutToBeDeleted();
        this.__provideDateState.aboutToBeDeleted();
        this.__provideMapState.aboutToBeDeleted();
        this.__provideSetState.aboutToBeDeleted();
        this.__provideUnionState.aboutToBeDeleted();
        SubscriberManager.Get().delete(this.id__());
        this.aboutToBeDeletedInternal();
    }
    
    private __provideSimpleState: ObservedPropertyAbstractPU;
    get provideSimpleState() {
        return this.__provideSimpleState.get();
    }
    set provideSimpleState(newValue: number) {
        this.__provideSimpleState.set(newValue);
    }
    
    private __provideClassState: ObservedPropertyAbstractPU<StateClass
    
    >;
    get provideClassState() {
        return this.__provideClassState.get();
    }
    set provideClassState(newValue: StateClass) {
        this.__provideClassState.set(newValue);
    }
    
    private __provideInterfaceState: ObservedPropertyAbstractPU<StateInterface
    
    >;
    get provideInterfaceState() {
        return this.__provideInterfaceState.get();
    }
    set provideInterfaceState(newValue: StateInterface) {
        this.__provideInterfaceState.set(newValue);
    }
    
    private __provideArrayState: ObservedPropertyAbstractPU<StateClass[]
    
    >;
    get provideArrayState() {
        return this.__provideArrayState.get();
    }
    set provideArrayState(newValue: StateClass[]) {
        this.__provideArrayState.set(newValue);
    }
    
    private __provideDateState: ObservedPropertyAbstractPU<Date
    
    >;
    get provideDateState() {
        return this.__provideDateState.get();
    }
    set provideDateState(newValue: Date) {
        this.__provideDateState.set(newValue);
    }
    
    private __provideMapState: ObservedPropertyAbstractPU<Map
    
    >;
    get provideMapState() {
        return this.__provideMapState.get();
    }
    set provideMapState(newValue: Map) {
        this.__provideMapState.set(newValue);
    }
    
    private __provideSetState: ObservedPropertyAbstractPU<Set
    
    >;
    get provideSetState() {
        return this.__provideSetState.get();
    }
    set provideSetState(newValue: Set) {
        this.__provideSetState.set(newValue);
    }
    
    private __provideUnionState: ObservedPropertyAbstractPUundefined>;
    get provideUnionState() {
        return this.__provideUnionState.get();
    }
    set provideUnionState(newValue: number | undefined) {
        this.__provideUnionState.set(newValue);
    }
    initialRender() {
        this.observeComponentCreation2((elmtId, isInitialRender) => {
            Column.create();
        }, Column);
        this.observeComponentCreation2((elmtId, isInitialRender) => {
            Text.create(`@Consume provideSimpleState: ${this.provideSimpleState}`);
        }, Text);
        Text.pop();
        this.observeComponentCreation2((elmtId, isInitialRender) => {
            Text.create(`@Consume provideClassState: ${this.provideClassState.value}`);
        }, Text);
        Text.pop();
        this.observeComponentCreation2((elmtId, isInitialRender) => {
            Text.create(`@Consume provideInterfaceState: ${this.provideInterfaceState.value}`);
        }, Text);
        Text.pop();
        this.observeComponentCreation2((elmtId, isInitialRender) => {
            Text.create(`@Consume provideArrayState: ${this.provideArrayState.map(item => item.value).join(',')}`);
        }, Text);
        Text.pop();
        this.observeComponentCreation2((elmtId, isInitialRender) => {
            Text.create(`@Consume provideDateState: ${this.provideDateState}`);
        }, Text);
        Text.pop();
        this.observeComponentCreation2((elmtId, isInitialRender) => {
            Text.create(`@Consume provideMapState: ${Array.from(ObservedObject.GetRawObject(this.provideMapState))
                .map((kv: [
                number,
                string
            ]) => `${kv[0]}:${kv[1]}`)
                .join(',')}`);
        }, Text);
        Text.pop();
        this.observeComponentCreation2((elmtId, isInitialRender) => {
            Text.create(`@Consume provideSetState: ${Array.from(ObservedObject.GetRawObject(this.provideSetState)).join(',')}`);
        }, Text);
        Text.pop();
        this.observeComponentCreation2((elmtId, isInitialRender) => {
            Text.create(`@Consume provideUnionState: ${this.provideUnionState}`);
        }, Text);
        Text.pop();
        Column.pop();
    }
    rerender() {
        this.updateDirtyElements();
    }
}

@Provide

转换前后

转换成TS之后,和@State的操作类似。

  1. 将原有属性重写为getter和setter
  2. 声明一个以双下划线开头的私有属性,在getter和setter里访问私有属性的get和set方法
  3. 也会根据是简单类型还是复杂类型,生成 ObservedPropertySimplePU和ObservedPropertyObjectPU

image.png

初始化

@Provide除了生成 以双下划线开头的私有属性,还紧接着调用了 addProvidedVar

如果@Provide声明时还指定了可以重写的key。则会调用两次addProvidedVar,两个key指向同一个对象

image.png

ViewPU

首先创建了一个状态变量包装类ObsevedPropertyObjectPU的实例,然后调用addProvidedVar将这个实例传进去保存在providedVars_中

protected addProvidedVar(providedPropName: string, store: ObservedPropertyAbstractPU, allowOverride: boolean = false)

将状态变量存储到了 this.providedVars_ 这个Map中,我们在 鸿蒙ACE-ArkUI构建(二)、渲染控制和构建过程 分析过这个

image.png

providedVars_是一个Map

image.png

小结 见 框架行为 1.a.

@Consume 

转换前后

转换成TS之后,和@State的操作类似。

  1. 将原有属性重写为getter和setter
  2. 声明一个以双下划线开头的私有属性,在getter和setter里访问私有属性的get和set方法
  3. 不管是简单类型还是复杂类型,都是 ObservedPropertyAbstractPU,这个类是所有状态变量的父类 

image.png

初始化

Consume的初始化都是通过initializeConsume完成的

image.png

ViewPU
protected initializeConsume(providedPropName: string, consumeVarName: string): ObservedPropertyAbstractPU

这个方法会查找是否有对应key的provide变量。先查找自身的providedVars_ map,没有的话逐级往上查找父组件的providedVars_ map

image.png

ObservedPropertyAbstract
public createSync(factoryFunc: SynchedPropertyFactoryFunc): ObservedPropertyAbstract

可以看到createSync很简单,就是调用了一下传入的factoryFunc函数,在这里就是上面截图的factory。实际上最终返回了一个SynchedPropertyTwoWayPU的实例

image.png

小结 见 框架行为 1.

  1. @Provide实际上创建了一个ObservedPropertyAbstractPU类的实例。这个类也是@State等的状态变量的基类
  2. 然后将这个实例通过addProvideVar添加到本组件的providedVars_ map表中
  3. 子组件中的@Consume会在组件的constructor中查通过initializeConsume完成初始化,@Consume实际上最终创建了一个SynchedPropertyTwoWayPU。这个类也是@Link等的状态变量的基类
  4. initializeConsume会从自身开始逐层查找组件的providedVars_对应key的状态变量
  5. 我们可以简单的把@Provide和@Consume当成存储在Map中的@State和@Link

关联和更新UI 见鸿蒙ACE-状态分析@Link 的关联和更新UI部分

@Consume最终是创建了一个 SynchedPropertyTwoWayPU,和@Link的逻辑很相似。可以查看鸿蒙ACE-状态分析@Link 关联UI 部分

小结 见框架行为 2.  3.

总结

@Consume,@Provide建立关联的关系和@Link与 @State建立关联的方式非常类似。只不过@Link与@State是直接传递,@Consume与@Provide是逐层向上查找。

建立关联之后就和@Link与@State的几乎一样了

阅读全文
下载说明:
1、本站所有资源均从互联网上收集整理而来,仅供学习交流之用,因此不包含技术服务请大家谅解!
2、本站不提供任何实质性的付费和支付资源,所有需要积分下载的资源均为网站运营赞助费用或者线下劳务费用!
3、本站所有资源仅用于学习及研究使用,您必须在下载后的24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担!
4、本站站内提供的所有可下载资源,本站保证未做任何负面改动(不包含修复bug和完善功能等正面优化或二次开发),但本站不保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都100%无错或无bug!如有链接无法下载、失效或广告,请联系客服处理!
5、本站资源除标明原创外均来自网络整理,版权归原作者或本站特约原创作者所有,如侵犯到您的合法权益,请立即告知本站,本站将及时予与删除并致以最深的歉意!
6、如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
7、如果您喜欢该资源,请支持官方正版资源,以得到更好的正版服务!
8、请您认真阅读上述内容,注册本站用户或下载本站资源即您同意上述内容!
原文链接:https://www.shuli.cc/?p=20252,转载请注明出处。
0

评论0

显示验证码
没有账号?注册  忘记密码?