尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

HarmonyOS 多设备短视频开发: 22 — 状态管理 V2 装饰器体系

HarmonyOS 多设备短视频开发: 22 — 状态管理 V2 装饰器体系 22 — 状态管理 V2 装饰器体系一、引言状态管理 V1 存在对象深度观察受限、Prop 只同步一层、装饰器职责边界模糊等问题。HarmonyOS 5.0 起推出的状态管理 V2 以更清晰的职责划分、更强的类型约束和更细的观察粒度重塑了这套体系。本项目 multi-short-video 的 UI 层视频页、播放器、评论、个人作品、首页与全局状态WindowInfo全部采用 V2是 V2 工程的完整样板。本文以features/multishortvideoadaptivevideo/src/main/ets/view/AdaptiveVideo.ets、view/AdaptiveAVPlayer.ets、common/multishortvideobase/src/main/ets/utils/WindowUtil.ets为蓝本拆解 V2 装饰器家族。二、组件级 V2 装饰器ComponentV2、Local、Param、EventV2 自定义组件以 ComponentV2 声明内部状态分为三大类Local组件内私有状态、Param父组件传入的入参、Event父组件注入的事件回调。视频页 AdaptiveVideo.ets 的声明如下真实代码ComponentV2exportstruct AdaptiveVideo{LocalwindowInfo:WindowInfogetWindowInfoState();LocalcurIndex:number0;LocalshowComment:booleanfalse;LocalcurrentState:media.AVPlayerStateidle;LocalisSeeking:booleanfalse;LocalseekToTime:number-1;...}播放器子组件 AdaptiveAVPlayer.ets 展示 Param 与 Event 的用法ComponentV2exportstruct AdaptiveAVPlayer{ParamcurrentIndex:number-1;Paramindex:number0;ParamcurrentSource:string;ParamseekToTime:number-1;LocalcurrentState:media.AVPlayerStateidle;EventonStateNotify:(state:media.AVPlayerState)void(){};...}设计要点Local 只能就地初始化禁止由外部赋值天然杜绝状态来源不明。Param 由父组件传入、子组件只读修改 Param 不会回传父组件父组件重新渲染时以最新值覆盖。Event 注入回调子组件通过this.onStateNotify(state)把播放器状态上抛给父组件形成单向数据流状态在父、行为在父、子组件只上报事件。对比 V1Param 同时替代了 Prop 的单向入参与 Link 的部分场景且支持按引用Param(‘xxx’, { type: … }) 深度同步与按值两种传递策略。三、ObservedV2 与 Trace数据模型的深度观察V2 用 ObservedV2 装饰 class、Trace 标记需要观察的成员属性实现属性级精细观察。common/multishortvideobase/src/main/ets/utils/WindowUtil.ets中的全局窗口信息对象即是典型ObservedV2exportclassWindowInfo{TracepublicwindowStatusType:window.WindowStatusTypewindow.WindowStatusType.UNDEFINED;TracepublicisFullScreen:booleanfalse;Tracepublicorientation:window.Orientationwindow.Orientation.UNSPECIFIED;TracepublicwindowSize:window.Size{width:0,height:0};TracepublicwidthBp:WidthBreakpointWidthBreakpoint.WIDTH_XS;TracepublicheightBp:HeightBreakpointHeightBreakpoint.HEIGHT_SM;TracepublicstatusBarTopVp:number0;...}只有被 Trace 标记的属性才具备可观察性未标记属性修改不会触发 UI 刷新。这种显式可观察的设计避免了 V1 Observed 整体代理带来的性能开销与误刷新。数据源模型model/AvDataSourceModel.ets当前为纯数据类未加 Trace配合Local avDataSource: AvDataSourceModel[]使用当整个数组被替换时刷新列表属性级刷新按需引入 Trace 即可体现了观察粒度可按需选择的灵活性。四、Provider/ConsumerV2 的跨层级共享V2 中 Provider 提供数据、Consumer 消费同名数据替代 V1 的 Provide/Consume。根组件products/default/src/main/ets/view/Index.ets建立 Provider 树EntryComponentV2struct Index{LocalwindowInfo:WindowInfogetWindowInfoState();Provider(isDark)isDark:booleanfalse;Provider(pathStack)pathStack:NavPathStacknewNavPathStack();Provider(showSideComment)showSideComment:booleanfalse;Provider(showSideIndividual)showSideIndividual:booleanfalse;Provider(subTabIndex)subTabIndex:number4;...}视频页与播放器跨层消费AdaptiveVideo.ets 与 AdaptiveAVPlayer.ets 真实代码// AdaptiveVideo.etsConsumer(showSideComment)showSideComment:booleanfalse;Consumer(showSideIndividual)showSideIndividual:booleanfalse;Consumer(pathStack)pathStack:NavPathStacknewNavPathStack();Provider(windowSizeWidth)windowSizeWidth:Length0;Provider(windowSizeHeight)windowSizeHeight:Length0;Provider(commentCount)commentCount:Length0;// AdaptiveAVPlayer.etsConsumer(currentTime)currentProgress:number0;Consumer(duration)duration:number0;同文件内 Provider 与 Consumer 并存形成转发AdaptiveVideo 从根组件消费 showSideComment、pathStack又把播放进度 currentTime/duration 提供给播放器与进度条。V2 还支持 Provider 必须初始化、Consumer 就地初始化不依赖外部顺序等约束规避了 V1 中 Consume 找不到提供方时的运行期告警。五、V1 与 V2 差异对比与本项目选型维度V1V2组件装饰ComponentComponentV2私有状态StateLocal入参Prop/LinkParam支持按值/按引用事件回调普通函数属性Event类观察Observed整体代理ObservedV2 Trace属性级跨层共享Provide/ConsumeProvider/Consumer计算/监听Watch无前后值Monitor带变化前后值/ Computed编译期约束弱多依赖运行期强装饰器本地化/限制初始化本项目选择 V2 的原因可归结为三点一是播放器与窗口状态变化高频timeUpdate 每 500ms 触发、windowSizeChange 频繁属性级 Trace Monitor 能将刷新与副作用收敛到精确节点二是多设备工程组件复用度高Param/Event 的单向数据流让组件契约清晰、易于跨 HAP 复用三是 Monitor 能拿到变化前后值天然契合拖动进度条 → 跳转播放 → 回写进度这类联动逻辑见文章 23。六、WindowInfo 全局对象的 V2 实现WindowInfo 是全局唯一的窗口状态对象由getWindowInfoState()通过 AppStorageV2.connect 连接后全局共享// common/multishortvideobase/src/main/ets/utils/WindowUtil.etsexportconstWINDOW_INFO_STORAGE_KEYMultiShortVideoWindowInfo;exportfunctiongetWindowInfoState():WindowInfo{returnAppStorageV2.connectWindowInfo(WindowInfo,WINDOW_INFO_STORAGE_KEY,()newWindowInfo())!;}WindowUtil 单例在窗口回调onWindowSizeChange、onAvoidAreaChange中直接修改 mainWindowInfo 的 Trace 属性任何组件内的Local windowInfo: WindowInfo getWindowInfoState()都能感知变化并刷新。于是断点、避让区、沉浸状态这些应用级信息以类对象形式在 common 层定义、在任意产品/特性模块消费成为驱动全项目自适应布局的状态中枢。七、总结与最佳实践组件内私有状态一律 Local只读入参用 Param行为上抛用 Event保持单向数据流。数据模型按需加 ObservedV2/Trace对象属性需要细粒度刷新时标记纯数据容器不滥用。跨层级共享用 Provider/Consumer优先在页面根部Index.ets收敛全局 Providerkey 命名统一字符串常量。高频状态播放进度、窗口尺寸借助 Trace 属性级观察与 Monitor 联动避免整树刷新。全局单例对象WindowInfo用 AppStorageV2.connect 连接兼顾全局唯一与可观察具体见文章 24。
返回列表