【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) })
  }
}



相关推荐
我爱吃福鼎肉片1 小时前
【C++】——list
c++·vector·list
冯志浩3 小时前
Harmony NEXT:如何给数据库添加自定义分词
harmonyos·掘金·金石计划
爱桥代码的程序媛5 小时前
鸿蒙OpenHarmony【轻量系统芯片移植案例】标准系统方案之瑞芯微RK3568移植案例
嵌入式硬件·harmonyos·鸿蒙·鸿蒙系统·移植·openharmony·鸿蒙开发
AORO_BEIDOU6 小时前
防爆手机+鸿蒙系统,遨游通讯筑牢工业安全基石
5g·安全·智能手机·信息与通信·harmonyos
ahauedu8 小时前
案例分析-Stream List 中取出值最大的前 5 个和最小的 5 个值
数据结构·list
逢生博客17 小时前
Mac 搭建仓颉语言开发环境(Cangjie SDK)
macos·华为·鸿蒙
青柠_项目管理17 小时前
PMP证书持有者,在华为、腾讯一般能拿多少薪资?
华为·pmp
小强在此21 小时前
【基于开源鸿蒙(OpenHarmony)的智慧农业综合应用系统】
华为·开源·团队开发·智慧农业·harmonyos·开源鸿蒙
Reuuse1 天前
【HCIA-Datacom】华为VRP系统
服务器·网络·华为