HarmonyOS 鸿蒙Next页面状态为何未正常同步?
HarmonyOS 鸿蒙Next页面状态为何未正常同步?
本人是Flutter开发兼HarmonyOS开发,在按MVVM方案考虑做页面状态管理时遇到了一个百思不得解的问题;
我觉得是我对Harmony状态管理的底层认识出错了,跪求高人解答orz;
测试小组件如下,我发现在实际运行后,日志可以看到计时器的刷新动作,但中间Text中的文本并不会实际刷新;
求大佬解惑!
更多关于HarmonyOS 鸿蒙Next页面状态为何未正常同步?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
【方案一】使用emitter通知testVM所在的struct去更新数据,因为监听的动作只能在组件内,API 10之后class中的this不再指向struct,而[@State](/user/State)的属性监听只能在stauct下才会生效。
注意:emitter只有在真机才会生效,在预览器只会执行一次。
import { hilog } from '@kit.PerformanceAnalysisKit' import { emitter } from '@kit.BasicServicesKit'; [@Entry](/user/Entry) [@Component](/user/Component) struct Page048 { [@State](/user/State) testVM: TestVM = new TestVM() aboutToAppear(): void { emitter.on({ eventId: 1 }, (event) => { this.testVM.counter ++ // this.testVM = JSON.parse(JSON.stringify(this.testVM)) }); } build() { Text(`${this.testVM.counter}`) } }
class TestVM{ counter: number = 0
constructor(){ setInterval(() => {
<span class="hljs-comment"><span class="hljs-comment">// this.counter++</span></span> emitter.emit( { eventId: <span class="hljs-number"><span class="hljs-number">1</span></span>, priority: emitter.EventPriority.IMMEDIATE }, { data: { <span class="hljs-string"><span class="hljs-string">'data'</span></span>: <span class="hljs-number"><span class="hljs-number">33</span></span> } } ); hilog.debug(<span class="hljs-number"><span class="hljs-number">1233</span></span>, <span class="hljs-string"><span class="hljs-string">'TestVM'</span></span>, `<span class="hljs-keyword"><span class="hljs-keyword">new</span></span> count - ${<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.counter}`) }, <span class="hljs-number"><span class="hljs-number">1000</span></span>)
} }
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>
【方案二】使用@ObjectLink与@Observed,但和方案一类似,还是要考虑执行this.counter++时要保证是在struct中调用的,还有就是这种方式写起来比较麻烦,需要@ObjectLink需要写到一个新的组件里,所以代码要抽离出来一个新组件。参考代码如下
import { hilog } from ‘@kit.PerformanceAnalysisKit’
@Component struct Page048Child { @ObjectLink testVM: TestVM
aboutToAppear(): void { this.testVM.start() }
build() { Text(
${<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.testVM.counter}
) } }@Entry @Component struct Page048 { @State testVM: TestVM = new TestVM()
build() { Column() { Page048Child({ testVM: this.testVM }) } } }
@Observed class TestVM { counter: number = 0
// constructor(){ start() { setInterval(() => {
<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.counter++ hilog.debug(<span class="hljs-number"><span class="hljs-number">1233</span></span>, <span class="hljs-string"><span class="hljs-string">'TestVM'</span></span>, `<span class="hljs-keyword"><span class="hljs-keyword">new</span></span> count - ${<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.counter}`) }, <span class="hljs-number"><span class="hljs-number">1000</span></span>)
} }
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>
更多关于HarmonyOS 鸿蒙Next页面状态为何未正常同步?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
感谢!大佬,我观察到这些修改,都是保证struct内属性变化是由struct内部的方法发起的,而非内部属性自行更新;用emitter做event响应的方法很灵活,后续业务复杂了进一步拓展也可行
自己摸索了一下,实际需要由Component组件内部方法触发,才可以正常执行子组件的重建方法;
用了一个很丑陋的方案,添加了一个ViewModel的更新回调方法,由struct负责重写,来实现在struct内更新ViewModel组件,能够暂时解决问题;
实不相瞒,楼主还是Android开发菜鸡一个,这种问题很难不联想到Android在更新业务组件UI时需要显式注明runOnUIThread()的要求,即页面渲染的刷新必须在UI线程进行,希望能进一步学习,了解底层逻辑~
HarmonyOS 鸿蒙Next页面状态未正常同步,可能的原因及解决方案如下:
- 状态变量未正确更新:检查是否在页面组件的状态变量更新时存在问题,确保更新操作是在组件内部方法触发,且正确使用了@State、@Link等装饰器。
- 父子组件同步问题:若涉及父子组件状态同步,需确认是否使用了正确的同步机制,如@Prop用于单向同步,@Link用于双向同步,对于多层关系的组件,可使用@Provide和@Consume装饰器。
- 异步更新未处理:若状态更新涉及异步操作,需确保异步操作完成后正确更新了状态变量,并触发了UI刷新。
- 性能或网络问题:页面状态同步可能受到设备性能或网络状况的影响,优化设备性能和网络环境可能有助于解决问题。
如果以上方法均无法解决问题,可能是系统或框架层面的bug,建议联系官网客服进行进一步排查和解决。官网地址是:https://www.itying.com/category-93-b0.html。