HarmonyOS 鸿蒙Next List lazyForeach List不能更新

发布于 1周前 作者 gougou168 来自 鸿蒙OS

HarmonyOS 鸿蒙Next List lazyForeach List不能更新

cke_254.png

使用List 懒加载是初始化可以,但是更新数据UI不刷新。查看了指南

如上图,是必须要实现一个DataChangeListener ,然后registerDataChangeListener 才能更新List UI吗?

如果是这样,DataChangeListener 要怎么实现呢?



关于HarmonyOS 鸿蒙Next List lazyForeach List不能更新的问题,您也可以访问:https://www.itying.com/category-93-b0.html 联系官网客服。

13 回复

希望HarmonyOS能继续加强在AI领域的研发,让系统更加智能化。

综上所述我猜测你可能出现问题的原因

LazyForEach(this.testList,(item:string,index:number) => {
          ListItem(){
            Row(){
              Text(`第${index}项数据为:${item}`)
            }.width(`100%`).height(`50`).onClick(() => {
              this.testList[index] = "lalala"
            })
          }
        })<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

你是直接修改了数据中某一项的值,此时修改的值并不会发生改变。如果想要实现点击后修改值然后列表更新需要在TestLazyDS中添加一个方法用于更改单独的一个item

public freshData(index:number,data: string):void{
    this.dataArray[index] = data
    this.notifyDataChange(index)
}<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

防止改变的值造成键值重复的问题最好在LazyForEach上添加键值处理,示例如下:

LazyForEach(this.testList,(item:string,index:number) => {
          ListItem(){
            Row(){
              Text(`第${index}项数据为:${item}`)
            }.width(`100%`).height(`50`).onClick(() => {
              this.testList.freshData(index,(parseInt(item)+20).toString())
            })
          }
        },(item:string,index:number) => item)<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

核心在两个,一个是更改数组后需要调用BasicDataSource中定义的onDataChange通知UI去更新列表,一个是

LazyForEach键值匿名函数keyGenerator重复造成的不刷新问题

参考文档:

https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ets-rendering-control-0000001149698611?ha_linker=eyJ0cyI6MTY5ODI4MDA3ODM3NSwiaWQiOiJmNGFiODVkMGE0OWVhMzA4NDdlMGM1OGIxZDNjODUzYyJ9#ZH-CN_TOPIC_0000001157228877__idatasource%E7%B1%BB%E5%9E%8B%E8%AF%B4%E6%98%8E

感谢,确实是因为键值的问题,需要主动设置一个,保证更新之后,键值也会更新

string[]这种数组类型就能更新,但如果改成模型数组就不行了,就是我数组里面存放不是字符串,而是我自定义的模型,这样就没有办法更新了,请问如何解决

很喜欢HarmonyOS的卡片式设计,信息一目了然,操作也更便捷。

大佬问题解决了没有,我也是模型数据。更新不了视图

求助:lazyforeach结合下拉刷新,拿到接口数据后,我先清空datasource,然后将新的数据源push进去,页面总是会先白屏闪一下,再显示数据,而不是像之前用foreach 直接从老数据变成新数据展示

这个DataChangeListener不是你实现的,是在使用的时候运行环境来实现的,然后添加到你的IDataSource接口实现类的实例中,你要做的事情是数据变化之后,调用DataChangeListener的对应方法去通知数据发生了变化

官方文档:LazyForEach示例,其实就在你截图部分的下面,你的IDataSource实现类里面有registerDataChangeListener和unregisterDataChangeListener方法,你就当成是在运行过程中系统源码会来调用这2个方法,然后你在方法中保存传过来的DataChangeListener对象,数据有变化的时候(比如:MyDataSource对象向成员dataArray中push了一个数组成员,同时就调用一下notifyDataAdd方法,循环所有被register进来的listener,告知他们新增了一个数据

DataChangeListener类型说明

名称

描述

onDataReloaded(): void

重新加载所有数据。

onDataAdded(index: number): void (deprecated)

通知组件index的位置有数据添加。

onDataMoved(from: number, to: number): void (deprecated)

通知组件数据从from的位置移到to的位置。

onDataDeleted(index: number): void (deprecated)

通知组件index的位置有数据删除。

onDataChanged(index: number): void (deprecated)

通知组件index的位置有数据变化。

onDataAdd(index: number): void 8+

通知组件index的位置有数据添加。

onDataMove(from: number, to: number): void 8+

通知组件数据从from的位置移到to的位置。

onDataDelete(index: number): void 8+

通知组件index的位置有数据删除。

onDataChange(index: number): void 8+

通知组件index的位置有数据变化。

// xxx.ets

class BasicDataSource implements IDataSource {

  private listeners: DataChangeListener[] = []

  public totalCount(): number {

    return 0

  }

  public getData(index: number): any {

    return undefined

  }

  registerDataChangeListener(listener: DataChangeListener): void {

    if (this.listeners.indexOf(listener) < 0) {

      console.info('add listener')

      this.listeners.push(listener)

    }

  }

  unregisterDataChangeListener(listener: DataChangeListener): void {

    const pos = this.listeners.indexOf(listener);

    if (pos >= 0) {

      console.info('remove listener')

      this.listeners.splice(pos, 1)

    }

  }

  notifyDataReload(): void {

    this.listeners.forEach(listener => {

      listener.onDataReloaded()

    })

  }

  notifyDataAdd(index: number): void {

    this.listeners.forEach(listener => {

      listener.onDataAdd(index)

    })

  }

  notifyDataChange(index: number): void {

    this.listeners.forEach(listener => {

      listener.onDataChange(index)

    })

  }

  notifyDataDelete(index: number): void {

    this.listeners.forEach(listener => {

      listener.onDataDelete(index)

    })

  }

  notifyDataMove(from: number, to: number): void {

    this.listeners.forEach(listener => {

      listener.onDataMove(from, to)

    })

  }

}

class MyDataSource extends BasicDataSource {

  // 初始化数据列表

  private dataArray: string[] = ['/path/image0.png', '/path/image1.png', '/path/image2.png', '/path/image3.png']

  public totalCount(): number {

    return this.dataArray.length

  }

  public getData(index: number): any {

    return this.dataArray[index]

  }

  public addData(index: number, data: string): void {

    this.dataArray.splice(index, 0, data)

    this.notifyDataAdd(index)

  }

  public pushData(data: string): void {

    this.dataArray.push(data)

    this.notifyDataAdd(this.dataArray.length - 1)

  }

}

[@Entry](/user/Entry)

[@Component](/user/Component)

struct MyComponent {

  private data: MyDataSource = new MyDataSource()

  build() {

    List({ space: 3 }) {

      LazyForEach(this.data, (item: string) => {

        ListItem() {

          Row() {

            Image(item).width(50).height(50)

            Text(item).fontSize(20).margin({ left: 10 })

          }.margin({ left: 10, right: 10 })

        }

        .onClick(() => {

          // 每点击一次列表项,数据增加一项

          this.data.pushData('/path/image' + this.data.totalCount() + '.png')

        })

      }, item => item)

    }

  }

}

https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ets-rendering-control-0000001149698611

我这里试,列表项数据增加没问题。但是更新已有到列表项数据不会刷新,调用了notifyDataChange 也不管用

关于懒加载中有详细的代码示例,直接扒下来即可

参考文档:

https://developer.harmonyos.com/cn/docs/documentation/doc-guides-V3/arkts-rendering-control-lazyforeach-0000001524417213-V3

interface IDataSource {
  totalCount(): number;                                             // 获得数据总数
  getData(index: number): any;                                      // 获取索引值对应的数据
  registerDataChangeListener(listener: DataChangeListener): void;   // 注册数据改变的监听器
  unregisterDataChangeListener(listener: DataChangeListener): void; // 注销数据改变的监听器
}
interface DataChangeListener {
  onDataReloaded(): void;                      // 重新加载数据时调用
  onDataAdd(index: number): void;            // 添加数据时调用
  onDataMove(from: number, to: number): void; // 数据移动起始位置与数据移动目标位置交换时调用
  onDataDelete(index: number): void;          // 删除数据时调用
  onDataChange(index: number): void;          // 改变数据时调用
}

export class BasicDataSource implements IDataSource { private listeners: DataChangeListener[] = [];

public totalCount(): number { return 0; }

public getData(index: number): any { return undefined; }

registerDataChangeListener(listener: DataChangeListener): void { if (this.listeners.indexOf(listener) < 0) { this.listeners.push(listener); } }

unregisterDataChangeListener(listener: DataChangeListener): void { const pos = this.listeners.indexOf(listener); if (pos >= 0) { this.listeners.splice(pos, 1); } }

notifyDataReload(): void { this.listeners.forEach(listener => { listener.onDataReloaded(); }) }

notifyDataAdd(index: number): void { this.listeners.forEach(listener => { listener.onDataAdd(index); }) }

notifyDataChange(index: number): void { this.listeners.forEach(listener => { listener.onDataChange(index); }) }

notifyDataDelete(index: number): void { this.listeners.forEach(listener => { listener.onDataDelete(index); }) }

notifyDataMove(from: number, to: number): void { this.listeners.forEach(listener => { listener.onDataMove(from, to); }) } }<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

import { BasicDataSource } from ‘./BasicDataSource’;

export class TestLazyDS extends BasicDataSource { private dataArray = Array<string>();

public totalCount(): number { return this.dataArray.length; }

public getData(index: number): any { return this.dataArray[index]; }

public addData(index: number, data: string): void { this.dataArray.splice(index, 0, data); this.notifyDataAdd(index); }

public pushData(data: string): void { this.dataArray.push(data); this.notifyDataAdd(this.dataArray.length - 1); }

public pushAllData(data: Array<string>): void { this.dataArray.length = 0 this.dataArray.push(…data); this.notifyDataReload(); } }<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

我这里试,列表项数据增加没问题。但是更新已有到列表项数据不会刷新,调用了notifyDataChange 也不管用

求助求助,有华为的大佬吗?

回到顶部