HarmonyOS鸿蒙Next中class对象数组(a)里面有对象数组(b),其中a用来展示纵向列表,b用来在a里面展示横向列表,当我更新了b对象数组,UI无法更新
HarmonyOS鸿蒙Next中class对象数组(a)里面有对象数组(b),其中a用来展示纵向列表,b用来在a里面展示横向列表,当我更新了b对象数组,UI无法更新 上图为效果图
下面是代码
@Entity({
tableName: 'routine_enum_entity',
})
@Observed
export class RoutineEnumEntity {
@Columns({
name: 'id',
type: ColumnType.TEXT,
isPrimaryKey: true,
})
id: string|null = null; // 主键
@Columns({ name: 'dic_text', type: ColumnType.TEXT })
dicText: string | null = null;
@Columns({ name: 'dic_value', type: ColumnType.TEXT })
dicValue: string | null = null;
@Columns({ name: 'dic_code', type: ColumnType.TEXT })
dicCode: string | null = null;
@Columns({ name: 'create_time', type: ColumnType.TEXT })
createTime: string | null = null;
photoList: PhotoEntity[] = [];
}
@Entry
@Component
struct RoutineCheckListPage {
@State controller: RefreshController = new RefreshController(); // 刷新控制器,声明全局变量
@State routineViewModel: RoutineViewModel = new RoutineViewModel();
@State titleModel: TitleBar.Model = new TitleBar.Model()
.setOnLeftClickListener(() => {
router.back();
});
@State enumList: RoutineEnumEntity[] = [];
@State dicValue: string = '';
@State dicCode: string = '';
@State maxTitleHeight: number = -1;
@State maxItemAllHeight: number = -1;
private context = getContext() as common.UIAbilityContext;
private filePath = "";
/// 获取项目列表
getEnumList() {
this.routineViewModel.getEnumNextList(this.dicValue).then(values => {
this.enumList = [...values];
this.controller.finishRefresh();
});
}
aboutToAppear(): void {
this.filePath = `${this.context.filesDir}/${CommonConstants.CONTRACT_ID}&${CommonConstants.MODULE_ID}`;
const params = (router.getParams() as ParamsEntity);
this.dicValue = params.type!;
this.dicCode = params.code!;
this.titleModel.titleName = params.titleName!;
this.getEnumList();
}
build() {
Column() {
TitleBar({ model: this.titleModel })
.padding({ top: 40 })
.backgroundColor($r('app.color.white'));
ListView({
items: this.enumList, // 数据源 数组, 任意类型
itemLayout: (item) => this.itemLayout(item as RoutineEnumEntity),
controller: this.controller, // 控制器,负责关闭下拉和上拉
isLazyData: false, // 禁止懒加载,也就是使用 ForEach 进行数据加载
onRefresh: () => {
// 下拉刷新
this.getEnumList();
}
}).layoutWeight(1);
}
.alignItems(HorizontalAlign.Start)
.width('100%')
.height('100%')
.backgroundColor($r('app.color.common_f5f6f6'));
}
// 相册选择图片/视频
selectDefault(photoList:PhotoEntity[]) {
DialogHelper.showActionSheetDialog({
title: "请选择上传方式",
sheets: ["相机", "从手机相册选择"],
onAction: (index) => {
if (index == 0) {
let options: CameraOptions = {
mediaTypes: [cameraPicker.PickerMediaType.PHOTO],
cameraPosition: camera.CameraPosition.CAMERA_POSITION_BACK,
saveUri: this.filePath, // 图片保存路径
};
PickerUtil.camera(options).then(result => {
LogUtil.debug(`调用相机,返回 uri:\n${result.resultUri}`);
const newPhoto = new PhotoEntity();
newPhoto.fileUri = result.resultUri;
photoList = [...photoList, newPhoto]; // 使用新数组替换旧数组
}).catch(err: BusinessError => {
showToast(`调用相机异常:\n${JSON.stringify(err)}`);
});
} else {
PhotoHelper.select().then(uris => {
let ps: Permissions[] = ['ohos.permission.WRITE_IMAGEVIDEO'];
PermissionUtil.requestPermissions(ps).then(result => {
if (result) {
uris.forEach((uri, index) => {
LogUtil.debug(`photoList1:\n${uri}`);
ImageHelper.compressPhoto(uri, this.filePath, index)
.then(compressUri => {
const newPhoto = ImageHelper.savePhotoEntity(uri, compressUri);
photoList = [...photoList, newPhoto]; // 使用新数组替换旧数组
LogUtil.debug('photoList2,' + JSON.stringify(photoList));
});
});
} else {
showToast("请在设置中打开权限");
WantUtil.toAppSetting();
}
});
});
}
}
});
}
/**
* Author: AbnerMing
* Describe: 条目布局
* @param item 数据对象
* @param index 数据索引
*/
@Builder
itemLayout(item: RoutineEnumEntity): void {
// 条目视图,任意组件
RelativeContainer() {
Column() {
Row() {
Text(item.dicText)
.fontSize(14)
.fontColor($r('app.color.common_333333'))
.margin(10)
.layoutWeight(1);
Image($r('app.media.ic_right'))
.height(20)
.padding({ right: 10 });
}
.width('100%')
.backgroundColor($r('app.color.white'))
.height(this.maxTitleHeight == -1 ? undefined : this.maxTitleHeight)
.onAreaChange((oldArea: Area, newArea: Area) => {
if (this.maxTitleHeight < newArea.height) {
this.maxTitleHeight = newArea.height as number;
}
})
.onClick(() => {
router.pushUrl({
url: RoutePath.RoutineDefectBindingPage,
params: {
type: item.dicValue,
}
});
});
Row() {
RelativeContainer() {
Image($r('app.media.ic_camera_a'))
.width(40)
.height(40)
.alignRules({
center: { anchor: '__container__', align: VerticalAlign.Center },
middle: { anchor: '__container__', align: HorizontalAlign.Center }
});
}
.width(90)
.height(90)
.align(Alignment.Center)
.borderRadius(2)
.borderStyle(BorderStyle.Dotted)
.borderWidth(1)
.borderColor($r('app.color.common_gray_66'))
.stateStyles({
normal: {
.backgroundColor($r('app.color.common_f5f6f6'))
},
pressed: {
.backgroundColor($r('app.color.white'))
},
})
.onClick(() => {
this.selectDefault(item.photoList);
})
.backgroundColor($r('app.color.common_main_color'));
ListView({
items: item.photoList, // 数据源 数组, 任意类型
itemLayout: (item) => this.childListItemBuild(item as PhotoEntity),
controller: this.controller, // 控制器,负责关闭下拉和上拉
isLazyData: false, // 禁止懒加载,也就是使用 ForEach 进行数据加载
isRefreshSticky: false,
enableRefresh: false,
enableLoadMore: false,
listAttribute: (attr) => {
attr.listDirection = Axis.Horizontal;
}
})
.layoutWeight(1)
.width('100%') // 确保宽度设置为 100%
.height('auto') // 使用 'auto' 确保高度自适应内容
}
.margin(10)
.width('100%') // 确保宽度设置为 100%
.height('auto') // 使用 'auto' 确保高度自适应内容
.alignItems(VerticalAlign.Top);
}
.width('100%')
.alignItems(HorizontalAlign.Start)
.backgroundColor($r('app.color.common_f5f6f6'));
}
.height(this.maxTitleHeight + 100)
.borderRadius(10)
.margin({ top: 10 })
.backgroundColor($r('app.color.common_f5f6f6'))
.align(Alignment.Center);
}
@Builder
childListItemBuild(photo: PhotoEntity) {
RelativeContainer() {
Image(photo.fileUri)
.width('100%')
.height(90)
.alignRules({
center: { anchor: '__container__', align: VerticalAlign.Center },
middle: { anchor: '__container__', align: HorizontalAlign.Center }
}).borderRadius(10);
}.height(100).width(90).margin({left: 10})
}
}
@Entity(
{
tableName: 'photo_file',
index: [
{
name: 'idIndex',
columnName: ['id'],
unique: true
}
]
}
)
@Observed
export class PhotoEntity {
@Columns({
name: 'id',
type: ColumnType.TEXT
})
id: string | null = null; // 唯一标识
@Columns({
name: 'file_uri',
type: ColumnType.TEXT
})
fileUri: string | null = null; // 照片路径URI
}
更多关于HarmonyOS鸿蒙Next中class对象数组(a)里面有对象数组(b),其中a用来展示纵向列表,b用来在a里面展示横向列表,当我更新了b对象数组,UI无法更新的实战教程也可以访问 https://www.itying.com/category-93-b0.html
9 回复
你好:
请参考:
[【HarmonyOS NEXT】@Observed和@ObjectLink嵌套对象属性更改UI不刷新问题 | 华为开发者联盟](https://developer.huawei.com/consumer/cn/blog/topic/03170446044769034)
[【HarmonyOS NEXT】深入理解@Observed装饰器和@ObjectLink装饰器:嵌套类对象属性变化 | 华为开发者联盟](https://developer.huawei.com/consumer/cn/blog/topic/03164568848167010)
给a对象的第一个数据重新赋值试一下勒,不要单独修改a对象里的某个b对象
有要学HarmonyOS AI的同学吗,联系我:https://www.itying.com/goods-1206.html
想请教一下@column是什么写法呢?好像从来没用过这种方式,是TS的装饰器语法糖?还是仓颉的语法呢?
希望给一个官方链接,想要学习了解下。
鸿蒙自己的数据库还是外部数据库呢
基于sqlite封装的,
在HarmonyOS鸿蒙Next中,如果更新了对象数组b
但UI未刷新,可能是因为数据绑定未正确触发。确保以下几点:
- 数据绑定:确保
a
和b
都使用了@State
或@Observed
装饰器,以便在数据变化时自动更新UI。 - 列表组件:使用
ForEach
或LazyForEach
来渲染列表,确保列表项在数据变化时重新渲染。 - 更新方法:在更新
b
时,使用this.b = [...this.b]
或this.b.splice(index, 1, newItem)
等方式,确保数组引用变化,触发UI更新。 - 状态管理:如果使用
@State
,确保在父组件中正确管理状态,避免状态丢失。
通过这些步骤,可以确保UI在数据更新时正确刷新。