【HarmonyOS】List组件多层对象嵌套ForEach渲染更新的处理

【HarmonyOS】List组件多层对象嵌套ForEach渲染更新的处理

问题背景:

在鸿蒙中UI更新渲染的机制,与传统的Android IOS应用开发相比。开发会简单许多,开发效率提升显著。

一般传统应用开发的流程处理分为三步:1.画UI,2.获得or创建,处理数据,3.增删改数据,找到对应控件,更新到UI上。

而鸿蒙应用开发,大大提供效率其中一点,就是减少了第三步。我们只需要关心数据源的变化,数据自动会更新到对应的控件上。

这种处理机制,其实符合应用开发的时代潮流,目前Android和IOS最新框架机制都有相应类似的处理。例如swiftUI,Compose。并且Vue,Flutter整个刷新机制就是如此。

众所周知,在HarmonyOs的list组件渲染中,如果数据源列表对象是多个对象嵌套的处理,那最底层对象的属性更新时,UI界面是不会渲染的。因为检测不到,目前只能检测到第一层对象。

解决方案:

当然官方的api在持续迭代的过程中。对于冗余渲染,渲染的性能提升,还有多层对象嵌套的数据源更新问题,一直再迭代方法处理。

针对多层对象嵌套,底层对象属性修改后,UI不渲染的问题,有个比较简单又方便的处理方式,思路仅供参考。

即:深拷贝修改的item对象。

这样整个对象相当于都变化了,就符合第一层对象检测的机制,可以被系统捕获到刷新。

DEMO示例:

dart 复制代码
import { util } from '@kit.ArkTS';

/**
 * 二级数据结构
 */
class ChildInfo {
  index: number;

  constructor(index: number) {
    this.index = index;
  }
}

/**
 * 一级数据结构
 */
class ItemInfo {
  key: string = util.generateRandomUUID(true);
  name: string;
  icon: Resource;
  childInfo: ChildInfo;
  select: boolean;

  constructor(name: string, icon: Resource, index: number) {
    this.name = name;
    this.icon = icon;
    this.childInfo = new ChildInfo(index);
    this.select = false;
  }

  /**
   * 重新创建对象,深拷贝处理
   * @param itemInfo
   * @param index
   * @returns
   */
  static deepCopy(itemInfo: ItemInfo, index: number){
    let info: ItemInfo = new ItemInfo(itemInfo.name, itemInfo.icon, index);
    info.select = itemInfo.select;
    info.key = itemInfo.key;
    info.childInfo = itemInfo.childInfo;
    return info;
  }
}

/**
 *
 */
@Entry
@Component
struct ForeachPage {

  private TAG: string = "ForeachPage";

  @State mListData: Array<ItemInfo> = [];

  aboutToAppear(): void {
    this.mListData.push(new ItemInfo('游戏', $r("app.media.iconA"), 1));
    this.mListData.push(new ItemInfo('游戏', $r("app.media.iconB"), 2));
    this.mListData.push(new ItemInfo('游戏', $r("app.media.iconA"), 3));
    this.mListData.push(new ItemInfo('游戏', $r("app.media.iconB"), 4));
    this.mListData.push(new ItemInfo('游戏', $r("app.media.iconA"), 5));
    this.mListData.push(new ItemInfo('游戏', $r("app.media.iconB"), 6));
  }

  @Builder ItemView(item: ItemInfo, index: number){
    Row() {
      Image(item.icon)
        .width(px2vp(120))
        .height(px2vp(120))

      Text(item.name + "(" + item.childInfo.index + ")").fontSize(20)

      Blank()

      if(this.isLog(item, index)){
        if(item.select){
          Image($r("app.media.icon_check"))
            .size({
              width: px2vp(72),
              height: px2vp(72)
            })
        }
      }
    }
    .width('100%')
    .justifyContent(FlexAlign.Start)
    .onClick(()=>{
      item.select = !item.select;
      if(item.select){
        item.childInfo.index = 666;
      }else{
        item.childInfo.index = index;
      }
      this.mListData[index] = ItemInfo.deepCopy(item, item.childInfo.index);
      console.log(this.TAG, " ItemView onClick: " + index + " item.select: " + item.select);
    })
  }

  private isLog(item: ItemInfo, index: number){
    console.log(this.TAG, " ItemView isLog index: " + index + " item.select: " + item.select);
    return true;
  }

  build() {
    List() {
      ForEach(this.mListData, (item: ItemInfo, index: number) => {
        ListItem() {
          this.ItemView(item, index)
        }
      }, (item: ItemInfo) => JSON.stringify(item))
      //
    }
    .width("100%")
    .height("100%")
    .padding({ left: px2vp(60), right: px2vp(60) })
  }
}



相关推荐
交叉编译之王 hahaha37 分钟前
RK3568-鸿蒙5.1镜像烧录与调试
华为·harmonyos
Raink老师43 分钟前
鸿蒙页面布局入门
华为·harmonyos·鸿蒙·移动端布局
hbcui19842 小时前
uni-app x正式支持鸿蒙原生应用开发
uni-app·harmonyos·uni-app x
lqj_本人2 小时前
鸿蒙OS&UniApp制作支持多图上传的图片选择器:打造高性能移动端上传体验#三方框架 #Uniapp
华为·uni-app·harmonyos
晚秋大魔王3 小时前
OpenHarmony 开源鸿蒙南向开发——linux下使用make交叉编译第三方库——wget
java·linux·运维·开发语言·华为·harmonyos
周胡杰13 小时前
组件导航 (HMRouter)+flutter项目搭建-混合开发+分栏效果
前端·flutter·华为·harmonyos·鸿蒙·鸿蒙系统
bestadc13 小时前
鸿蒙 Core File Kit(文件基础服务)之简单使用文件
harmonyos
Darkwanderor14 小时前
c++STL-list的模拟实现
c++·list
SuperHeroWu715 小时前
【HarmonyOS 5】鸿蒙星闪NearLink详解
华为·蓝牙·harmonyos·nearlink·鸿蒙星闪·绿牙
积跬步DEV17 小时前
RN 鸿蒙混合开发实践(踩坑)
react native·华为·harmonyos