HarmonyOS 鸿蒙Next LazyForEach 加载数据源时,当时数据源数据更变过后,页面UI没有展示最新的数据
HarmonyOS 鸿蒙Next LazyForEach 加载数据源时,当时数据源数据更变过后,页面UI没有展示最新的数据 我们是采用LazyForEach 加载数据源的,当时数据源数据更变过后,页面ui没有展示最新的数据;展示的还是旧数据源数据;
我们的demo代码如下:
@Entry
@Component
struct TestPage {
private moved: number[] = [];
@State private dataSource: ListDataSource<StringData> = new ListDataSource<StringData>();
num:number=0
aboutToAppear() {
this.num++
for (let i = 0; i <= 20; i++) {
this.dataSource.pushData(new StringData(`${this.num}_${i}`));
}
}
build() {
Column(){
List({ space: 3 }) {
LazyForEach(this.dataSource, (item: StringData, index: number) => {
ListItem() {
ChildComponent({data: item})
}
.onClick(() => {
item.message += '0';
})
}, (item: StringData, index: number) => index.toString())
.cachedCount(5)
.width("100%")
.layoutWeight(1)
Button("更换数据内容")
.margin(10)
.onClick(()=>{
//模拟从接口中获取到数据
setTimeout(()=>{
this.num++
let dataTemp:StringData[]=[]
for (let i = 0; i <= 20; i++) {
dataTemp.push(new StringData(`${this.num}_${i}`));
}
this.dataSource.setData(dataTemp)
},500)
})
}
}
}
@Component
struct ChildComponent {
@ObjectLink data: StringData
build() {
Row() {
Text(this.data.message).fontSize(50)
.onAppear(() => {
console.info("appear:" + this.data.message)
})
}.margin({ left: 10, right: 10 })
}
}
@Observed
class StringData {
message: string;
constructor(message: string) {
this.message = message;
}
}
export class ListDataSource<T> implements IDataSource {
private _data: T[] = [];
private _listeners: DataChangeListener[] = [];
constructor(initValue: T[] = []) {
this._data = initValue;
}
/**
* 设置懒数据
* @param src 要设置的数据源
*/
setData(src: T[]): void {
this._data = src;
this.notifyDataReload()
}
/**
* 通过给定搜索条件,查找第一个符合条件的元素下标
* @param predicates
* @returns
*/
getDataIndex(predicates: (el: T, i: number, arr: T[]) => boolean): number;
/**
* 查找给定元素在懒数据源中的下标
* @param searchEl
* @returns
*/
getDataIndex(searchEl: T): number;
getDataIndex(predicates: T | ((el: T, i: number, arr: T[]) => boolean)): number {
if (typeof predicates == 'function') {
return this._data.findIndex(predicates as ((el: T, i: number, arr: T[]) => boolean));
}
return this._data.indexOf(predicates);
}
/**
* 向懒数据源末尾添加一个元素
* @param data 要添加的元素
*/
pushData(data: T): void {
this._data.push(data);
this.notifyDataAdd(this._data.length - 1);
}
/**
* 删除指定懒数据
* @param obj
*/
deleteData(obj: T): void;
/**
* 删除懒数据源中指定位置的元素
* @param index
*/
deleteData(index: number): void;
deleteData(predicates: number | T): void {
let index = -1;
if (typeof predicates == 'number') {
this._data.splice(predicates, 1);
index = predicates;
} else {
index = this.getDataIndex(predicates);
this._data.splice(index, 1);
}
this.notifyDataDelete(index);
}
/**
* 向懒数据源中插入一个元素,若不给定index,则添加到懒数据源的最前端
* @param data 要插入的数据
* @param index 插入位置
*/
insertData(data: T, index: number = 0): void {
this._data.splice(index, 0, data);
this.notifyDataAdd(index);
}
/**
* 删除懒数据源末尾的元素,返回被删除的元素
* @returns 被删除的元素
*/
popData(): T | undefined {
let data = this._data.pop();
this.notifyDataDelete(this._data.length);
return data;
}
/**
* 删除懒数据源的首个元素,返回被删除的元素
* @returns 被删除的元素
*/
shiftData(): T | undefined {
let data = this._data.shift();
this.notifyDataDelete(0);
return data;
}
/**
* 修改给定下标的元素
* @param index 给定的下标
* @param newData 修改后的元素
*/
modifyData(index: number, newData: T): void;
/**
* 修改指定元素为新元素
* @param predicates 要搜索的原元素
* @param newData 新元素
*/
modifyData(predicates: T, newData: T): void;
modifyData(predicates: number | T, newData: T): void {
let index = -1;
if (typeof predicates == 'number') {
index = predicates;
} else {
index = this.getDataIndex(predicates);
}
this._data[index] = newData;
this.notifyDataChange(index);
}
/**
* 将元素从from下标处移动至to下标处
* @param from
* @param to
*/
moveData(from: number, to: number): void {
let el_f = this._data[from];
this._data[from] = this._data[to];
this._data[to] = el_f;
this.notifyDataMove(from, to);
}
/**
* 从懒数据源中搜索符合条件的数据
* @param predicates
* @returns
*/
searchData(predicates: (value: T, index: number, array: T[]) => boolean): T[] {
return this._data.filter(predicates);
}
/**
* 获取懒数据总数
* @returns
*/
totalCount(): number {
return this._data.length;
}
/**
* 获取指定下标处的懒数据
* @param index
* @returns
*/
getData(index: number): T {
return this._data[index];
}
registerDataChangeListener(listener: DataChangeListener): void {
if (this._listeners.indexOf(listener) < 0) this._listeners.push(listener);
}
unregisterDataChangeListener(listener: DataChangeListener): void {
let index = this._listeners.indexOf(listener);
if (index > 0) this._listeners.splice(index, 1);
}
notifyDataReload(): void {
this._listeners.forEach(listener => {
listener.onDataReloaded();
});
}
notifyDataAdd(index: number): void {
this._listeners.forEach(listener => {
listener.onDataAdd(index);
});
}
notifyDataMove(from: number, to: number): void {
this._listeners.forEach(listener => {
listener.onDataMove(from, to);
});
}
notifyDataDelete(index: number): void {
this._listeners.forEach(listener => {
listener.onDataDelete(index);
});
}
notifyDataChange(index: number): void {
this._listeners.forEach(listener => {
listener.onDataChange(index);
});
}
}
更多关于HarmonyOS 鸿蒙Next LazyForEach 加载数据源时,当时数据源数据更变过后,页面UI没有展示最新的数据的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
因为咱们是删除数据源后重新添加的同数量的数据,所以键值不变导致组件没有重新渲染,可以修改下lasyforeach的键值生成策略,可以参考官网文档的限制条件的最后一条:
参考代码如下:
@Entry
@Component
struct TestPage {
private moved: number[] = [];
@State private dataSource: ListDataSource<StringData> = new ListDataSource<StringData>();
num:number=0
aboutToAppear() {
this.num++
for (let i = 0; i <= 20; i++) {
this.dataSource.pushData(new StringData(`${this.num}${i}`));
}
}
build() {
Column(){
List({ space: 3 }) {
LazyForEach(this.dataSource, (item: StringData, index: number) => {
ListItem() {
ChildComponent({data: item})
}
.onClick(() => {
item.message += '0';
})
}, (item: StringData, index: number) => item.toString())//修改点
}
.cachedCount(5)
.width("100%")
.layoutWeight(1)
Button("更换数据内容")
.margin(10)
.onClick(()=>{
//模拟从接口中获取到数据
setTimeout(() =>{
this.num++
let dataTemp:StringData[]=[]
for (let i = 0; i <= 20; i++) {
dataTemp.push(new StringData(`${this.num}${i}`));
}
this.dataSource.setData(dataTemp)
},500)
})
}
}
}
@Component
struct ChildComponent {
@ObjectLink data: StringData
build() {
Row() {
Text(this.data.message).fontSize(50)
.onAppear(() => {
console.info("appear:" + this.data.message)
})
}
.margin({ left: 10, right: 10 })
}
}
@Observed
class StringData {
message: string;
constructor(message: string) {
this.message = message;
}
}
export class ListDataSource<T> implements IDataSource {
private _data: T[] = [];
private _listeners: DataChangeListener[] = [];
constructor(initValue: T[] = []) {
this._data = initValue;
}
setData(src: T[]): void {
this._data = src;
this.notifyDataReload()
}
getDataIndex(predicates: (el: T, i: number, arr: T[]) => boolean): number;
getDataIndex(searchEl: T): number;
getDataIndex(predicates: T | ((el: T, i: number, arr: T[]) => boolean)): number {
if (typeof predicates == 'function') {
return this._data.findIndex(predicates as (el: T, i: number, arr: T[]) => boolean);
}
return this._data.indexOf(predicates);
}
pushData(data: T): void {
this._data.push(data);
this.notifyDataAdd(this._data.length - 1);
}
deleteData(obj: T): void;
deleteData(index: number): void;
deleteData(predicates: number | T): void {
let index = -1;
if (typeof predicates == 'number') {
this._data.splice(predicates, 1);
index = predicates;
} else {
index = this.getDataIndex(predicates);
this._data.splice(index, 1);
}
this.notifyDataDelete(index);
}
insertData(data: T, index: number = 0): void {
this._data.splice(index, 0, data);
this.notifyDataAdd(index);
}
popData(): T | undefined {
let data = this._data.pop();
this.notifyDataDelete(this._data.length);
return data;
}
shiftData(): T | undefined {
let data = this._data.shift();
this.notifyDataDelete(0);
return data;
}
modifyData(index: number, newData: T): void;
modifyData(predicates: T, newData: T): void;
modifyData(predicates: number | T, newData: T): void {
let index = -1;
if (typeof predicates == 'number') {
index = predicates;
} else {
index = this.getDataIndex(predicates);
}
this._data[index] = newData;
this.notifyDataChange(index);
}
moveData(from: number, to: number): void {
let el_f = this._data[from];
this._data[from] = this._data[to];
this._data[to] = el_f;
this.notifyDataMove(from, to);
}
searchData(predicates: (value: T, index: number, array: T[]) => boolean): T[] {
return this._data.filter(predicates);
}
totalCount(): number {
return this._data.length;
}
getData(index: number): T {
return this._data[index];
}
registerDataChangeListener(listener: DataChangeListener): void {
if (this._listeners.indexOf(listener) < 0) this._listeners.push(listener);
}
unregisterDataChangeListener(listener: DataChangeListener): void {
let index = this._listeners.indexOf(listener);
if (index > 0) this._listeners.splice(index, 1);
}
notifyDataReload(): void {
this._listeners.forEach(listener => {
listener.onDataReloaded();
});
}
notifyDataAdd(index: number): void {
this._listeners.forEach(listener => {
listener.onDataAdd(index);
});
}
notifyDataMove(from: number, to: number): void {
this._listeners.forEach(listener => {
listener.onDataMove(from, to);
});
}
notifyDataDelete(index: number): void {
this._listeners.forEach(listener => {
listener.onDataDelete(index);
});
}
notifyDataChange(index: number): void {
this._listeners.forEach(listener => {
listener.onDataChange(index);
});
}
}
更多关于HarmonyOS 鸿蒙Next LazyForEach 加载数据源时,当时数据源数据更变过后,页面UI没有展示最新的数据的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS鸿蒙系统中,使用Next LazyForEach加载数据源时,如果数据源数据发生变化但页面UI没有展示最新数据,这通常是由于数据绑定或状态管理的问题。
鸿蒙系统的UI框架在数据更新时依赖于数据绑定机制来自动刷新界面。如果数据源更新但UI未更新,可能是因为:
-
数据源未正确触发更新:确保你的数据源是一个可观察的对象,并且在数据变化时能够触发UI的重新渲染。在鸿蒙系统中,你可以使用特定的数据绑定机制或状态管理库来实现这一点。
-
组件未正确订阅数据源:检查Next LazyForEach组件是否正确订阅了数据源的变化。如果组件没有订阅数据源的变化,那么即使数据源更新,组件也不会收到通知来更新UI。
-
UI框架的缓存机制:有时UI框架可能会缓存某些组件的状态,以防止不必要的重新渲染。确保你的组件在数据变化时能够正确触发重新渲染。
如果以上检查都无误,但问题依旧存在,可能是UI框架的特定行为或bug。此时,你可以考虑查阅鸿蒙系统的官方文档或社区论坛,看看是否有其他开发者遇到并解决了类似的问题。
如果问题依旧没法解决请联系官网客服,官网地址是 https://www.itying.com/category-93-b0.html