HarmonyOS鸿蒙Next中Refresh+List渲染异常

HarmonyOS鸿蒙Next中Refresh+List渲染异常 功能很简单, 下拉刷新时候刷新接口, 发现刷新完以后ui 列表变成了倒序, 但是数据和日志都是正常的啊, 鸿蒙渲染失效了?还是我的装饰器有问题?希望有大佬指点下

刷新前

cke_7801.png

下拉刷新后,并且点击了第一条数据

cke_9669.png

两次调用数据的日志

cke_18069.png

下拉刷新的代码

Refresh({ refreshing: $$this.isRefreshing }) {
  List({ scroller: this.scroller }) {
    Repeat<MsgConversationItem>(this.msgViewModel.msgConversationItem)
      .each((reItem) => {
        ListItem() {
          this.setItemInfo(reItem.item)
        }.width('100%')
        .onClick(() => {
          Toast.showToast("点击了:" + reItem.index + "-----姓名:" + reItem.item.otherNickname)
        })
      })
  }
  .width('100%')
  .listDirection(Axis.Vertical)
  .alignListItem(ListItemAlign.Center)
  .scrollBar(BarState.Off)
  .divider({
    strokeWidth: 1,
    color: $r('app.color.sys_gray_color'),
    startMargin: 10,
    endMargin: 10
  })

}
.layoutWeight(1)
.onRefreshing(() => {
  setTimeout(() => {
    this.isRefreshing = false;
  }, 2000)
 this.msgViewModel.getConversationList();
})

装饰器代码

@ObservedV2
export class MsgViewModel extends BaseVM<BaseState> {

  private service: MsgService = new MsgService();

  @Trace msgConversationItem: Array<MsgConversationItem> = []

  public constructor() {
    super(new BaseState());
  }


  getConversationList() {
    this.service.getConversationList((msgdata) => {
      this.msgConversationItem = Array.from(msgdata.rows!)
      for (let i = 0; i < this.msgConversationItem.length; i++) {
        Logger.error(TAG, "indx" + i + "----" + this.msgConversationItem[i].otherNickname)
      }
    });
    
  }


  public sendEvent(callback: () => void) {


  }
}

从现象上看好像是数据没问题, 就是渲染出现错乱或者有没有类似安卓list的notifychange()方法?


更多关于HarmonyOS鸿蒙Next中Refresh+List渲染异常的实战教程也可以访问 https://www.itying.com/category-93-b0.html

7 回复

应该是没有设置键值生成函数.key造成的:

Repeat<MsgConversationItem>(this.msgViewModel.msgConversationItem)
  .each((reItem) => {
    ListItem() {
      this.setItemInfo(reItem.item)
    }.width('100%')
    .onClick(() => {
      Toast.showToast("点击了:" + reItem.index + "-----姓名:" + reItem.item.otherNickname)
    })
  })
  .key(reItem => reItem.id)

更多关于HarmonyOS鸿蒙Next中Refresh+List渲染异常的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


还真是, 感谢大佬,

总的来说,HarmonyOS是一款非常优秀的操作系统,期待它能在未来带给我们更多惊喜!

那你点击的时候数据是正确的吗,比如我点第一个是王丽雅,我第二张图片还点第一个是谁?,

点击的顺序和日志打出的顺序一致, 只有ui显示是倒序的, 每刷一次ui就倒序一次, 但是从日志看拿的数据是没问题的,

在HarmonyOS Next中,Refresh与List组件结合使用时,渲染异常通常由数据源更新与UI刷新不同步导致。检查Refresh组件的refreshing状态是否在数据加载完成后正确重置。确保List的数据源更新操作在UI主线程执行,避免异步回调中直接修改数据引发布局错乱。可尝试使用状态管理或@State装饰器同步数据状态。

根据你提供的代码和现象,问题很可能出在 ArkTS UI 框架的列表渲染机制 上,特别是 @ObservedV2 装饰的数组被整体替换时,Repeat 渲染可能出现异常。

核心问题分析:

  1. 数据与 UI 绑定失效:你的 msgConversationItem 数组使用 @Trace 装饰,并在 getConversationList() 中通过 this.msgConversationItem = Array.from(msgdata.rows!) 整体替换了数组。虽然数据顺序在日志中正确,但 Repeat 组件可能无法正确识别数组项的变化,导致渲染顺序错乱。

  2. Repeatkey 缺失Repeat 渲染动态列表时,如果列表项缺少唯一标识符(key),框架在数组被整体替换后可能无法高效复用现有组件,从而引发渲染顺序问题。

解决方案:

方案一:为 Repeat 添加 key(推荐)Repeat 中指定每个列表项的唯一标识符(如 id),帮助框架正确跟踪和复用组件:

Repeat<MsgConversationItem>(this.msgViewModel.msgConversationItem)
  .each((reItem) => {
    ListItem() {
      this.setItemInfo(reItem.item)
    }
    .key(reItem.item.id) // 假设列表项有唯一 id 字段
    .width('100%')
    .onClick(() => {
      Toast.showToast("点击了:" + reItem.index + "-----姓名:" + reItem.item.otherNickname)
    })
  })

方案二:避免数组整体替换 改为修改原数组内容(如清空后追加新数据),而非直接赋值新数组:

getConversationList() {
  this.service.getConversationList((msgdata) => {
    // 清空原数组
    this.msgConversationItem.length = 0;
    // 追加新数据
    this.msgConversationItem.push(...Array.from(msgdata.rows!));
    for (let i = 0; i < this.msgConversationItem.length; i++) {
      Logger.error(TAG, "indx" + i + "----" + this.msgConversationItem[i].otherNickname)
    }
  });
}

方案三:使用 @Observed 装饰数组项 如果 MsgConversationItem 是类,可将其用 @Observed 装饰,并在 Repeat 中直接绑定:

@ObservedV2
export class MsgViewModel extends BaseVM<BaseState> {
  @Trace msgConversationItem: Array<MsgConversationItem> = []
  // ...
}

// MsgConversationItem 类
@Observed
export class MsgConversationItem {
  // 属性定义
}

总结: 优先采用 方案一(添加 key,这是解决列表渲染顺序问题的标准做法。如果问题依旧,可结合方案二(避免整体替换数组)。方案三适用于复杂数据结构场景。

回到顶部