鸿蒙开发在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获取桌面配置信息

  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

// 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() {
。。。。。。

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/962452.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

中国网络安全产业分析报告

网络安全是总体国家安全观的重要组成部分&#xff0c;切实维护网络空间安全&#xff0c;筑牢国家网络安全屏障&#xff0c;已成为关系我国发展全局的重大战略任务。近年来&#xff0c;我国网信相关部门深入推进网络安全治理&#xff0c;网络安全政策法规体系更加健全&#xff0…

kimi,天工,gpt,deepseek效果对比

偶然间碰到的这个问题&#xff0c;这个问题感觉有点意思&#xff0c;他不是定义性的问题&#xff0c;而是不同概念之间的区别对比&#xff0c;我觉得这个效果立竿见影&#xff0c;一看就能看出来回答问题水平的层次。 单纯这个问题的答案&#xff0c;deepseek远超gpt&#xff…

Github 2025-01-30 Go开源项目日报 Top10

根据Github Trendings的统计,今日(2025-01-30统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Go项目10Ollama: 本地大型语言模型设置与运行 创建周期:248 天开发语言:Go协议类型:MIT LicenseStar数量:42421 个Fork数量:2724 次关注人…

MySQL查询优化(三):深度解读 MySQL客户端和服务端协议

如果需要从 MySQL 服务端获得很高的性能&#xff0c;最佳的方式就是花时间研究 MySQL 优化和执行查询的机制。一旦理解了这些&#xff0c;大部分的查询优化是有据可循的&#xff0c;从而使得整个查询优化的过程更有逻辑性。下图展示了 MySQL 执行查询的过程&#xff1a; 客户端…

【4Day创客实践入门教程】Day3 实战演练——桌面迷你番茄钟

Day3 实战演练——桌面迷你番茄钟 目录 Day3 实战演练——桌面迷你番茄钟1. 选择、准备元件、收集资料2. 硬件搭建3.编写代码 Day0 创想启程——课程与项目预览Day1 工具箱构建——开发环境的构建Day2 探秘微控制器——单片机与MicroPython初步Day3 实战演练——桌面迷你番茄钟…

leetcode 2300. 咒语和药水的成功对数

题目如下 数据范围 示例 注意到n和m的长度最长达到10的5次方所以时间复杂度为n方的必然超时。 因为题目要求我们返回每个位置的spell对应的有效对数所以我们只需要找到第一个有效的药水就行&#xff0c;这里可以先对potions排序随后使用二分查找把时间复杂度压到nlogn就不会…

Android Studio 正式版 10 周年回顾,承载 Androider 的峥嵘十年

Android Studio 1.0 宣发于 2014 年 12 月&#xff0c;而现在时间来到 2025 &#xff0c;不知不觉间 Android Studio 已经陪伴 Androider 走过十年历程。 Android Studio 10 周年&#xff0c;也代表着了我的职业生涯也超十年&#xff0c;现在回想起来依然觉得「唏嘘」&#xff…

互斥锁/信号量实现5个线程同步

互斥锁 实现同步 互斥锁保证在同一时刻&#xff0c;只有一个线程可以访问共享资源&#xff0c;从而实现了线程同步。 思路 1 创建互斥锁(1个) pthread_mutex_t mutex; 2 初始化互斥锁 所有线程开始执行前&#xff0c;pthread_mutex_init(&mutex, …

WordPress Web Directory Free插件本地包含漏洞复现(附脚本)(CVE-2024-3673)

免责申明&#xff1a; 本文所描述的漏洞及其复现步骤仅供网络安全研究与教育目的使用。任何人不得将本文提供的信息用于非法目的或未经授权的系统测试。作者不对任何由于使用本文信息而导致的直接或间接损害承担责任。如涉及侵权&#xff0c;请及时与我们联系&#xff0c;我们将…

系统学习算法: 专题七 递归

递归算法简而言之就是当一个大问题拆分为多个子问题时&#xff0c;如果每个子问题的操作步骤都一样&#xff0c;就可以用递归&#xff0c;其中递归在递的时候要有结束条件&#xff0c;不能一直递下去&#xff0c;结束条件后就归 这里不建议学习递归的时候抠细节&#xff0c;还…

单片机基础模块学习——PCF8591芯片

一、A/D、D/A模块 A——Analog 模拟信号:连续变化的信号(很多传感器原始输出的信号都为此类信号)D——Digital 数字信号:只有高电平和低电平两种变化(单片机芯片、微控制芯片所能处理的都是数字信号) 下面是模拟信号和连续信号的区别 为什么需要进行模拟信号和数字信号之…

从未标记图像中生成有标记图像特征的半监督分割方法

今天看到一篇文章很有意思&#xff0c;给大家分享一下。现在传统半监督分割网络训练时往往有标注数据与未标注数据分开训练&#xff0c;导致模型不好。这篇文章作者提出了一个很有意思的想法。它通过通道注意力从未标记的特征中重新加载标记的特征。这篇文章是AllSpark。 大家感…

17.1 图像操作

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 17.1.1 Image类 Image类为源自 Bitmap 和 Metafile 的类提供功能的抽象基类。 Image的属性大多数是只读的&#xff1a; FrameDim…

实验七 JSP内置对象II

实验七 JSP内置对象II 目的&#xff1a; 1、掌握JSP内置对象的使用。 2、理解JSP的作用域 3、掌握session&#xff0c;application对象的使用 实验要求&#xff1a; 1、完成实验题目 2、要求提交实验报告&#xff0c;将代码和实验结果页面截图放入报告中 实验过程&#xff1a…

每日一博 - 三高系统架构设计:高性能、高并发、高可用性解析

文章目录 引言一、高性能篇1.1 高性能的核心意义 1.2 影响系统性能的因素1.3 高性能优化方法论1.3.1 读优化&#xff1a;缓存与数据库的结合1.3.2 写优化&#xff1a;异步化处理 1.4 高性能优化实践1.4.1 本地缓存 vs 分布式缓存1.4.2 数据库优化 二、高并发篇2.1 高并发的核心…

FFmpeg(7.1版本)的基本组成

1. 前言 FFmpeg 是一个非常流行的开源项目&#xff0c;它提供了处理音频、视频以及其他多媒体内容的强大工具。FFmpeg 包含了大量的库&#xff0c;可以用来解码、编码、转码、处理和播放几乎所有类型的多媒体文件。它广泛用于视频和音频的录制、转换、流媒体传输等领域。 2. F…

灵芝黄金基因组注释-文献精读109

The golden genome annotation of Ganoderma lingzhi reveals a more complex scenario of eukaryotic gene structure and transcription activity 灵芝&#xff08;Ganoderma lingzhi&#xff09;的黄金基因组注释揭示了更复杂的真核基因结构和转录活性情况 摘要 背景 普遍…

51单片机入门_01_单片机(MCU)概述(使用STC89C52芯片;使用到的硬件及课程安排)

文章目录 1. 什么是单片机1.1 微型计算机的组成1.2 微型计算机的应用形态1.3 单板微型计算机1.4 单片机(MCU)1.4.1 单片机内部结构1.4.2 单片机应用系统的组成 1.5 80C51单片机系列1.5.1 STC公司的51单片机1.5.1 STC公司单片机的命名规则 2. 单片机的特点及应用领域2.1 单片机的…

记忆化搜索(5题)

是什么&#xff1f; 是一个带备忘录的递归 如何实现记忆化搜索 1.添加一个备忘录&#xff08;建立一个可变参数和返回值的映射关系&#xff09; 2.递归每次返回的时候把结果放到备忘录里 3.在每次进入递归的时候往备忘录里面看看。 目录 1.斐波那契数列 2.不同路径 3.最…

Redis_Redission的入门案例、多主案例搭建、分布式锁进行加锁、解锁底层源码解析

目录 ①. Redis为什么选择单线程&#xff1f; ②. 既然单线程这么好,为什么逐渐又加入了多线程特性&#xff1f; ③. redis6的多线程和IO多路复用入门篇 ④. Redis6.0默认是否开启了多线程&#xff1f; ⑤. REDIS多线程引入总结 ①. Redis为什么选择单线程&#xff1f; ①…