现象
进入sdk页面后,点击页面中的发送指令进入loading状态,切到非sdk页面再切回sdk页面,此时sdk页面显示比正常进入sdk页面异常
原因
app集成sdk页面时,切换tab时重现初始化了sdk页面。会重新走aboutApear从storage里面拿数据来刷新ui。在出现问题的场景时,发送指令后appStorege的一个属性被修改,重新创建view时,该数据没有恢复,所以不对应。
由于问题出现复杂业务里面,逻辑嵌套比较多,要一层一层分析。如果用一个demo来说明就是component生命周期和该页面数据生命周期没有对应。
分析:
一、storage的定义:
AppStorage是应用全局的UI状态存储,是和应用的进程绑定的,由UI框架在应用程序启动时创建,为应用程序UI状态属性提供中央存储。
和AppStorage不同的是,LocalStorage是页面级的,通常应用于页面内的数据共享。而AppStorage是应用级的全局状态共享。
二:demo简化分析
下面是一个抽象出来的简单demo
import { router } from '@kit.ArkUI'
let localStorage = new LocalStorage()
@Entry({ storage: localStorage })
@Component
struct TestPage {
@LocalStorageLink("storage_text") localStorage_text: string = '默认'
@StorageProp("storage_text") appStorage_text: string = "默认"
aboutToAppear(): void {
console.log("aboutToAppear")
}
aboutToDisappear(): void {
console.log("aboutToDisappear")
// AppStorage.setOrCreate("storage_text", "默认")
}
build() {
Column() {
Text(this.localStorage_text)
// Text(this.appStorage_text)
.fontSize(30)
.fontColor(Color.Red)
.onClick(() => {
this.localStorage_text = '被点击'
// AppStorage.setOrCreate("storage_text", "被点击")
})
.gesture(LongPressGesture().onAction(() => {
router.replaceUrl({url:"pages/TestPage"})
}))
}.width('100%')
.height('100%')
.alignItems(HorizontalAlign.Center)
}
}
如果使用appStorage来保存数据,在click触发时,text被修改。这时长按进入一个新的页面(模拟页面重新创建),text不是预期的“默认”。
原因就是数据和view的生命周期不一致导致的,理论上view重新创建,数据也应该恢复默认值。但是这里因为用了appStorage,一个是页面生命周期,一个是app生命周期,当然就没法对应。
三、解决办法
那么解决方案有2个方向:
1.ui和数据生命周期对应。系统提供了页面级别的storage:LocalStorage,它在页面重新创建时也会重新初始化。
2.在ui销毁时,重置appStorage的数据。demo上就是在aboutApear是把appStorage中的text重置。
四、延伸
appStorage和localStorage各有优势,appStorage在跨页面,跨模块通信时使用非常方便。这边修改,那边去观察即可。
localStorage在跨页面通信没那么方便,但是生命周期和页面一致,同生共死,不用去额外处理生命周期不一致导致的bug。
良好的app体验应该在创建ui时,借助持久化数据以及云端数据,尽量恢复上一次的状态。比如项目中的发送指令后的loading状态,在杀掉app再重新打开app时,如果还处于loading状态要恢复对应的ui。