开天辟地 HarmonyOS(鸿蒙) - 组件(列表类): List(LazyForEach 的应用)

源码 https://github.com/webabcd/HarmonyDemo
作者 webabcd

开天辟地 HarmonyOS(鸿蒙) - 组件(列表类): List(LazyForEach 的应用)

示例如下:

pages\component\list\ListDemo6.ets

/** List - LazyForEach 的应用** LazyForEach 支持懒挂载(仅在 List, Grid, Swiper, WaterFlow 中有效)* 懒挂载的意思就是,一个显示大量数据的 List 滚动后,会挂载(onAppear)正在显示的 item,且会卸载(onDisAppear)未显示的 item,从而减少资源占用*/import { MyLog, TitleBar } from '../../TitleBar';
import { LengthMetrics } from '@kit.ArkUI';@Entry
@Component
struct ListDemo6 {build() {Column() {TitleBar()Tabs() {TabContent() { MySample1() }.tabBar('基础').align(Alignment.Top)}.scrollable(true).barMode(BarMode.Scrollable).layoutWeight(1)}}
}@Component
struct MyItem {item: string = "";aboutToAppear() {MyLog.d(`aboutToAppear:${this.item}`)}aboutToDisappear(): void {MyLog.d(`aboutToDisappear:${this.item}`)}build() {ListItem() {Text(this.item).width('100%').fontSize(24).textAlign(TextAlign.Center).backgroundColor(Color.Orange).borderRadius(20).height(50)}.margin({ left: 20, right: 20 }).onAppear(() => {// item 挂载到组件树上时MyLog.d(`onAppear:${this.item}`)}).onDisAppear(() => {// item 从组件树上卸载时MyLog.d(`onDisAppear:${this.item}`)})}
}
@Component
struct MySample1 {private data: MyDataSource = new MyDataSource(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19']);build() {Column({space:10}) {Flex({wrap: FlexWrap.Wrap, direction: FlexDirection.Row, space:{ main: LengthMetrics.vp(10), cross: LengthMetrics.vp(10) }}) {Button("添加").onClick(() => this.data.addData(0, Math.floor(Math.random() * 1000).toString()))Button("删除").onClick(() => this.data.deleteData(0))Button("更新").onClick(() => this.data.changeData(0, Math.floor(Math.random() * 1000).toString()))Button("移动").onClick(() => this.data.moveData(0, 2))Button("交换").onClick(() => this.data.exchangeData(0, 2))Button("刷新全部").onClick(() => this.data.reloadData())Button("批量操作").onClick(() => this.data.batchOperation())}/** List - 列表*   cachedCount() - 指定预挂载的 item 的数量(仅 LazyForEach 或 Repeat 结合 List, Grid, Swiper, WaterFlow 时有效)*     要支持 item 的预挂载,需要使用 LazyForEach 或 Repeat(关于 List 结合 Repeat 的应用请参见 /component/list/ListDemo7.ets 中的说明)*     每次除了挂载可视区的 item 外,还会在上和下分别预挂载指定数量的 item(其他的 item 会被卸载)** LazyForEach - 在 ForEach 的基础上支持懒挂载(数据来自一个 IDataSource 对象)*   LazyForEach 的第 3 个参数是 keyGenerator 用于生成 item 的键值,其作用请参见 ListDemo5.ets 中的说明*   LazyForEach 的 onMove() 用于实现拖动排序,请参见 ListDemo5.ets 中的说明** 注:* 1、item 被创建时会走到 aboutToAppear,item 被销毁时会走到 aboutToDisappear* 2、item 挂载到组件树上时会走到 onAppear,item 从组件树上卸载时会走到 onDisAppear* 3、item 从组件树上卸载之后,就会被销毁,下次再使用时会重新创建*/List({ space: 10 }) {LazyForEach(this.data, (item: string, index: number) => {MyItem({item:`${item}`})}, (item: string, index: number) => item).onMove((from:number, to:number) => {// 注:这里的代码仅用于更新数据源,而界面上的排序是由框架自己实现的(也就是说即使没有下面的代码,也不影响界面上的排序)this.data.moveData_withoutNotify(from, to)})}.cachedCount(5)}.margin({ left: 20, right: 20 })}
}// 实现 IDataSource 接口,用于管理 listener 监听,以及通知 LazyForEach 做相关操作并刷新
// 注:这个类用于为 LazyForEach 提供数据,以及于通知 LazyForEach 做相关操作并刷新,但是它并不会更新数据源
class BasicDataSource implements IDataSource {private listeners: DataChangeListener[] = [];private originDataArray: string[] = [];public totalCount(): number {return this.originDataArray.length;}public getData(index: number): string {return this.originDataArray[index];}// 此方法会由框架自动调用,用于为 LazyForEach 组件的数据源注册 listener 监听registerDataChangeListener(listener: DataChangeListener): void {if (this.listeners.indexOf(listener) < 0) {this.listeners.push(listener);}}// 此方法会由框架自动调用,用于为 LazyForEach 组件的数据源注销 listener 监听unregisterDataChangeListener(listener: DataChangeListener): void {const pos = this.listeners.indexOf(listener);if (pos >= 0) {this.listeners.splice(pos, 1);}}// 通知 LazyForEach 组件,需要在位置 index 处添加 itemnotifyDataAdd(index: number): void {this.listeners.forEach(listener => {listener.onDatasetChange([{type: DataOperationType.ADD, index: index}]);// 上面的相当于下面的,但是在一个 IDataSource 内,onDatasetChange 和 onDataXXX 不能混用,否则可能会报错 Error: onDatasetChange cannot be used with other interface// listener.onDataAdd(index);})}// 通知 LazyForEach 组件,在位置 index 处的 item 发生了变化notifyDataChange(index: number): void {this.listeners.forEach(listener => {listener.onDatasetChange([{type: DataOperationType.CHANGE, index: index}]);// 上面的相当于下面的,但是在一个 IDataSource 内,onDatasetChange 和 onDataXXX 不能混用,否则可能会报错 Error: onDatasetChange cannot be used with other interface// listener.onDataChange(index);})}// 通知 LazyForEach 组件,需要删除位置 index 处的 itemnotifyDataDelete(index: number): void {this.listeners.forEach(listener => {listener.onDatasetChange([{type: DataOperationType.DELETE, index: index}]);// 上面的相当于下面的,但是在一个 IDataSource 内,onDatasetChange 和 onDataXXX 不能混用,否则可能会报错 Error: onDatasetChange cannot be used with other interface// listener.onDataDelete(index);})}// 通知 LazyForEach 组件,将位置 from 的 item 移动到位置 tonotifyDataMove(from: number, to: number): void {this.listeners.forEach(listener => {listener.onDatasetChange([{type: DataOperationType.MOVE, index: {from: from, to: to}}]);})}// 通知 LazyForEach 组件,将位置 index1 和 index2 的 item 互换notifyDataExchange(index1: number, index2: number): void {this.listeners.forEach(listener => {listener.onDatasetChange([{type: DataOperationType.EXCHANGE, index: {start: index1, end: index2}}]);})}// 通知 LazyForEach 组件,需要重载所有 itemnotifyDataReload(): void {this.listeners.forEach(listener => {listener.onDatasetChange([{type: DataOperationType.RELOAD}]);// 上面的相当于下面的,但是在一个 IDataSource 内,onDatasetChange 和 onDataXXX 不能混用,否则可能会报错 Error: onDatasetChange cannot be used with other interface// listener.onDataReloaded();})}// 通知 LazyForEach 组件,需要并行执行多个指定的操作notifyDatasetChange(operations: DataOperation[]): void {this.listeners.forEach(listener => {listener.onDatasetChange(operations);})}
}// BasicDataSource 实现了 IDataSource 接口,用于管理 listener 监听,以及通知 LazyForEach 做相关操作并刷新
// MyDataSource 继承自 BasicDataSource,增加了更新源数据的逻辑
class MyDataSource extends BasicDataSource
{private dataArray: string[] = [];constructor(dataArray: string[]) {super();this.dataArray = dataArray}public totalCount(): number {return this.dataArray.length;}public getData(index: number): string {return this.dataArray[index];}public addData(index: number, data: string): void {// 更新源数据this.dataArray.splice(index, 0, data);// 通知 LazyForEach 做相关操作并刷新this.notifyDataAdd(index);}public deleteData(index: number): void {// 更新源数据this.dataArray.splice(index, 1);// 通知 LazyForEach 做相关操作并刷新this.notifyDataDelete(index);}public changeData(index: number, data: string): void {// 更新源数据this.dataArray.splice(index, 1, data);// 通知 LazyForEach 做相关操作并刷新this.notifyDataChange(index);}public moveData(from: number, to: number): void {// 更新源数据let tmp = this.dataArray.splice(from, 1)this.dataArray.splice(to, 0, tmp[0])// 通知 LazyForEach 做相关操作并刷新this.notifyDataMove(from, to);}public moveData_withoutNotify(from: number, to: number): void {// 更新源数据let tmp = this.dataArray.splice(from, 1)this.dataArray.splice(to, 0, tmp[0])}public exchangeData(index1: number, index2: number): void {// 更新源数据let temp: string = this.dataArray[index1];this.dataArray[index1] = this.dataArray[index2];this.dataArray[index2] = temp;// 通知 LazyForEach 做相关操作并刷新this.notifyDataExchange(index1, index2);}public reloadData(): void {// 更新源数据this.dataArray = this.dataArray.map((item: string) => {return item + 'x';})// 通知 LazyForEach 做相关操作并刷新this.notifyDataReload();}public batchOperation(): void {// 更新源数据// 懒得写了,反正要知道 listener.onDatasetChange() 用于通知 LazyForEach 做相关操作并刷新,但是它并不会更新数据源// 同样的,更新了数据源之后,也不会让 LazyForEach 做相关操作并刷新// 通知 LazyForEach 并行执行多个指定的操作并刷新(注意是并行执行所有逻辑,而不是串行执行)this.notifyDatasetChange([{ type: DataOperationType.DELETE, index: 0, count: 1 },{ type: DataOperationType.MOVE, index: { from: 1, to: 2 } },// { type: DataOperationType.ADD, index: 0, count: 1 },// { type: DataOperationType.EXCHANGE, index: { start: 0, end: 1 } },// { type: DataOperationType.CHANGE, index: 0 },// { type: DataOperationType.RELOAD },]);}
}

源码 https://github.com/webabcd/HarmonyDemo
作者 webabcd

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/879506.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

美国支付清算体系介绍

美国的支付清算体系是全球最复杂、最多样化的金融基础设施之一,支撑着庞大的国内经济和全球金融活动。本文将详细介绍美国支付清算体系的主要组成部分,包括银行间支付系统(如Fedwire和CHIPS)和零售支付系统(如ACH、Zelle、RTP),并探讨它们的特点和应用场景。通过对比中国…

学习 -人工智能 - AI Agent的理解

浅谈AI Agent的理解 Agents是什么? 大语言模型可以接收输入、可以分析&推理、可以输出文字、代码、媒体。然而其无法像人类一样,拥有规划思考能力、运用各种工具与物理世界互动,以及拥有人类的记忆能力。 AI Agents是基于LLM能够自助理解、自主规划决策、执行复杂任务的…

dotnet LibGit2Sharp 使用笔记

本文记录我对 LibGit2Sharp 库的使用笔记LibGit2Sharp 库开源地址: https://github.com/libgit2/libgit2sharp 本文使用的版本是: 0.31.0 按照 dotnet 的惯例,使用之前先用 NuGet 安装,安装之后的 csproj 文件代码大概如下 <Project Sdk="Microsoft.NET.Sdk"&…

dotnet 9 已知问题 默认开启 CET 导致进程崩溃

本文记录 dotnet 9 的一个已知且当前已修问题。默认开启 CET 导致一些模块执行时触发崩溃官方文档: Breaking change: CET supported by default - .NET Microsoft Learn 表现: 调用 OpenFileDialog 的 ShowDialog 将会异常崩溃,崩溃异常是 FAST_FAIL_SET_CONTEXT_DENIED 或…

读算法简史:从美索不达米亚到人工智能时代08组合优化

读算法简史:从美索不达米亚到人工智能时代08组合优化1. 组合优化 1.1. 蛮力搜索算法会尝试所有可能的组合并从中选择最好的那个 1.2. 旅行商问题是众多组合优化(combinatorial optimization)问题中的一个,它要求许多固定元素以可能的最佳方式进行组合1.2.1. 固定元素可以有无…

[Vie] 依赖预构建

使用Vite模板vue-ts. https://github.com/vitejs/vite/tree/main/packages/create-vite 一个组件在没加入Lodash之前:当加入lodash之后,会自动把它加入到.vite/deps中去: 假如不用依赖构建 vite.config.tsreturn {plugins: [vue()],// ...optimizeDeps: {exclude: [lodash-…

从源码分析arm64中断与GIC

本文以树莓派4b(armv8)来实现,4b支持两种传统的中断控制器 gic-400 但是使用的qemu和实际的板子都是默认支持gic-400的,所以主要是借助gic-400实现中断的功能异常处理 相关寄存器PSTATE 就是cpu状态DAIF 调试异常 SError(系统异常) IRQ(中断) FIQ(快速中断)esr_elx 用来保存返…

《gm/ID设计法基本介绍》翻译

最近流片很累很焦虑,放松心情找篇讲\(g_m/I_D\)设计法的文档翻译一下: 《A Basic Introduction to the gm/ID-Based Design Methodology》 1. 摘要 该文章向读者介绍了基于\(g_m/I_D\)的设计方法学,用于帮助CMOS模拟电路设计者将晶体管物理参数与小信号模型联系起来,文章的…

个人英语学习笔记基于B站英语的平行世界语法课程

导读 语言学习没有捷径,只要听说读写这四大行长期日复一日的练习就行了,兴趣是最重要的,兴趣就是高效学习的基础和长期坚持下去的动力。 0基础开始痛苦学习大半年英语,没兴趣的结果就是词汇量是上去了,但是英语的听说读写水平还不如学了一年的日语。😅 该笔记基于此课程…

PostgreSQL:数据库迁移与版本控制

title: PostgreSQL:数据库迁移与版本控制 date: 2025/2/6 updated: 2025/2/6 author: cmdragon excerpt: 在现代软件开发中,数据库作为应用程序的核心组件之一,数据的结构和内容必须能够随着业务需求的变化而调整。因此,数据库迁移和版本控制成为了确保数据一致性、完整性…

Servlet基础

什么是Servlet、Servlet的架构、Servlet任务、Servlet的基本使用、Servlet的生命周期、Servlet API中主要接口及实现类、Servlet的部署(注册与映射)、缺省Servlet与启动时加载配置、ServletConfig与ServletContext、request和response什么是Servlet基础 Java Servlet 是运行在…

GNURadio模块学习——Source and Sink类

介绍GNU Radio中常见的 Source 与 Sink 模块,包括流程图端口、音频输入输出、虚拟连接、文件读写、ZMQ跨流程图通信,以及随机信号源、固定信号源、噪声源等常见信号源和时域、频域、星座图等信号展示工具。Source and Sink Pad(流程图端口) 当该流程图是hierarchical block…