鸿蒙开发在onPageShow中数据加载不完整的问题分析与解决

API Version 12

1、onPageShow()作什么的

首先说明下几个前端接口的区别:

ArkUI-X的aboutToAppear()接口是一个生命周期接口,用于在页面即将显示之前调用。

在ArkUI-X中,aboutToAppear()接口是一个重要的生命周期接口,它会在页面即将显示之前被调用。这个接口通常用于在页面显示之前进行一些准备工作,比如加载数据、初始化状态等。通过在aboutToAppear()方法中执行这些操作,可以确保页面在显示时已经准备好所需的数据和状态,提升用户体验。

ArkUI-X的onPageShow()方法在页面每次显示时调用‌。具体来说,当页面被切换显示时,onPageShow()会被触发一次,这通常发生在用户从其他页面返回当前页面或者应用进入前台时。

页面显示‌:当用户从其他页面返回当前页面时,onPageShow()会被调用。

应用进入前台‌:当应用从后台切换到前台时,onPageShow()也会被调用。

简单说,aboutToAppear()就是初始化加载执行一次。

onPageShow()每次页面切换显示时,都会执行一次。所以,如果是需要保持最新的数据,该数据在其他页面或后端会有修改,重新切换回当前页面,就需要重新读取数据,比如从后端重新获取。

2、当在onPageShow中多次异步获取数据会怎么样

下面代码步骤:

1)通过常量SysAppInfoList来更新this.appInfoList

2)通过bridge接口获取userAppInfoList数据后

3)将userAppInfoList合入this.appInfoList

4)刷新this.appInfoList的index

5)通过bridge获取桌面配置信息

TypeScript 复制代码
  async onPageShow() {
    this.appInfoList = SysAppInfoList;
    this.appInfoList.push(new ThirdPartyAppInfo("全部应用", "全部应用", "app.media.icon", 3, true))
    let userAppInfoList = await getThirdAppInfo()
    for (let i = 0; i < userAppInfoList.length; i++) {
      this.appInfoList.push(userAppInfoList[i])
    }
    for (let i = 0; i < this.appInfoList.length; i++) {
      this.appInfoList[i].index = i
    }

    let defaultMessage: string = '[{"家庭存储" : true}, {"网络录像机" : true}, {"智能助手" : true}]'
    this.desktopShowCfg = await getDesktopShowCfg(defaultMessage)

    console.info(`---homepage, initThirdAppInfo finish`);
  }

  isDeskShow(packageName: string): boolean {
    if (packageName.includes("全部应用")) {
      console.info(`---homepage isDeskShow, 全部应用`)
      return true;
    }
    for (let i = 0; i < this.desktopShowCfg.length; i++) {
      if (this.desktopShowCfg[i].packageName.includes(packageName)) {
        console.info(`---homepage isDeskShow, return false ` + packageName)
        return this.desktopShowCfg[i].flag
      }
    }
    console.info(`---homepage isDeskShow, not match ` + packageName)
    return false
  }

  @Builder
  AppListBuilder() {
    List() {
      ForEach(this.appInfoList, (info: ThirdPartyAppInfo) => {
        ListItem() {
          if (this.isDeskShow(info.packageName)) {
            Column() {
              Stack() {
。。。。。。

这里的this.appInfoList会触发页面的渲染,但是这里多次刷新了this.appInfoList,所以可能会导致无法预测的后果。

在页面渲染当中,会使用this.desktopShowCfg来判断是否在桌面显示。

相关日志如下:

2024-11-08 22:34:06.691 28646-28646 Ace com.example.helloworld I js_console_log.cpp(94) ---getThirdAppInfo 获取第三方应用信息

2024-11-08 22:34:06.715 28646-28646 getThirdAppInfo com.example.helloworld D ---third party app number: 4

2024-11-08 22:34:06.715 28646-28646 getThirdAppInfo com.example.helloworld D ---success

2024-11-08 22:34:06.722 28646-28646 Ace com.example.helloworld I js_console_log.cpp(94) ---homepage isDeskShow, not match 家庭存储

2024-11-08 22:34:06.722 28646-28646 Ace com.example.helloworld I js_console_log.cpp(94) ---homepage isDeskShow, not match 网络录像机

2024-11-08 22:34:06.723 28646-28646 Ace com.example.helloworld I js_console_log.cpp(94) ---homepage isDeskShow, not match 智能助手

2024-11-08 22:34:06.723 28646-28646 Ace com.example.helloworld I js_console_log.cpp(94) ---homepage isDeskShow, 全部应用

2024-11-08 22:34:06.731 28646-28646 Ace com.example.helloworld I js_console_log.cpp(94) ---getThirdAppInfo 获取第三方应用信息成功:{"appName":"HelloWorld","packageName":"com.example.helloworld1","appIcon":"\\/sdcard\\/appInfo\\/HelloWorld.png","isSys":false,"index":0}, {"appName":"MyApplication","packageName":"com.example.myapplication","appIcon":"\\/sdcard\\/appInfo\\/MyApplication.png","isSys":false,"index":1}, {"appName":"全民K歌","packageName":"com.tencent.karaoke","appIcon":"\\/sdcard\\/appInfo\\/全民K歌.png","isSys":false,"index":2}, {"appName":"哔哩哔哩","packageName":"tv.danmaku.bili","appIcon":"\\/sdcard\\/appInfo\\/哔哩哔哩.png","isSys":false,"index":3}

2024-11-08 22:34:06.731 28646-28646 Ace com.example.helloworld I js_console_log.cpp(94) ---getThirdAppInfo 获取第三方应用信息,解析成功,app数量为:4

2024-11-08 22:34:06.732 28646-28646 Ace com.example.helloworld I js_console_log.cpp(94) ---getDesktopShowCfg

2024-11-08 22:34:06.732 28646-28646 getDesktopShowCfg com.example.helloworld D ---read cfg file.

2024-11-08 22:34:06.742 28646-28646 Ace com.example.helloworld I js_console_log.cpp(94) ---getDesktopShowCfg: {"家庭存储" : true}, {"网络录像机" : true}, {"智能助手" : true}

2024-11-08 22:34:06.742 28646-28646 Ace com.example.helloworld I js_console_log.cpp(94) ---getDesktopShowCfg 解析成功,数量为:3

2024-11-08 22:34:06.742 28646-28646 Ace com.example.helloworld I js_console_log.cpp(94) ---homepage, initThirdAppInfo finish

从日志信息来看,this.appInfoList、this.desktopShowCfg也都成功加载了。但是单板测试时,所有桌面元素都被过滤了。

经过多组对比测试,原因分析应该是:this.appInfoList第一次赋值时,就开始触发桌面渲染,而因为多处异步处理(this.appInfoList、this.desktopShowCfg两个bridge都是异步),包括this.appInfoList也有多次赋值。所以在页面渲染完成后,this.desktopShowCfg还没来得及更新数据,就会造成页面加载的数据不完整。

3、解决方法是页面渲染数据归一,且一次性刷新

如下,将两次birdge获取数据的接口,合为一个接口,保证this.appInfoList一次刷新到位。

OnMainPage: boolean对应前面的this.desktopShowCfg

TypeScript 复制代码
// ThirdPartyAppInfoModel.ets
export class ThirdPartyAppInfo {
。。。。。。
  OnMainPage: boolean
。。。。。。  

// homePage.ets
async onPageShow() { 
    let defaultCfg: string = DefaultSysAppCfgOfHomePage
    // 返回包含sys app和third app的所有app列表
    this.appInfoList = await getThirdAppInfo(defaultCfg, sysAppList)
    // console.info(`---homepage, return all app: ` + this.appInfoList)
  }

  isDeskShow(info: ThirdPartyAppInfo): boolean {
    if (info.packageName.includes("全部应用")) {
      // console.info(`---homepage isDeskShow, 全部应用`)
      return true;
    }

    // console.info(`---homepage deskShow ` + info.packageName + ` match ` + info.OnMainPage)
    return info.OnMainPage
  }

  @Builder
  AppListBuilder() {
    List({scroller: this.listScroller}) {
      ForEach(this.appInfoList, (info: ThirdPartyAppInfo) => {
        ListItem() {
          if (this.isDeskShow(info)) {
            Column() {
              Stack() {
。。。。。。

这样改写后,页面加载就没有问题了,前端代码也相当的简洁,数据的整合处理都放在后端了。

相关推荐
Swift社区11 分钟前
鸿蒙游戏中的手势系统详解
游戏·华为·harmonyos
不羁的木木17 分钟前
Form Kit(卡片开发服务)学习笔记02-环境搭建与基础配置
笔记·学习·harmonyos
G_dou_22 分钟前
# Flutter+OpenHarmony 实战:ToDo待办清单
flutter·harmonyos
不羁的木木1 小时前
Form Kit(卡片开发服务)学习笔记04-交互事件与跳转处理
笔记·学习·交互·harmonyos
不爱吃糖的程序媛9 小时前
Flutter 三方库适配鸿蒙教程
flutter·华为·harmonyos
不羁的木木10 小时前
HarmonyOS文件基础服务(Core File Kit)实战演练04-文件监听与流式读写
华为·harmonyos
不羁的木木10 小时前
ArkWeb实战学习笔记05-综合实战:构建混合应用
笔记·学习·harmonyos
芒鸽12 小时前
鸿蒙应用测试实战:从单元测试到自动化测试
华为·单元测试·harmonyos
Davina_yu13 小时前
Hello HarmonyOS:搭建DevEco Studio开发环境与第一个应用运行(1)
harmonyos·鸿蒙原生开发
2501_9197490313 小时前
鸿蒙 Flutter 实战:video_compress 3.1.4 适配 3.27-ohos 全流程
flutter·华为·harmonyos