鸿蒙开发的懒加载你会用了么

262 阅读6分钟

大家好,对于近几年火热的鸿蒙开发,除了文档以外,AI并不能很好的给我们提供帮助,这就导致了如果我们看不明白文档,就不会用。今天就给大家分享一些对于鸿蒙开发中它的懒加载是如何实现并简单的应用,帮助大家理解进步。

本章篇幅较长,主要是中间有代码介绍和测试情况

image.png

特点

如果大家看到过官网的文档,简单来说就是在每次迭代过程中创建相应的组件,根据可视区域创建,滑出滚动区域就会销毁。进来就创建出去就销毁,满足了我们对于这个优化的相关要求

限制:

  • 仅list,grid,swiper以及waterFlow组件支持使用,
  • 只允许建立一个子组件
  • 必须使用DataChangeListener对象进行更新,是触发UI更新的对象 (必须要用这个对象,否则不变)
  • 等等(具体下面会给出官网文档的链接,可以详细了解)

了解官网给出的初始代码

下面是官网给出的初始代码,大家可以在初始代码的基础按自己的需求修改,那么我就来介绍一下,这段代码中,各个方法分别是做什么用的,毕竟使用工具之前就是要熟悉工具

image.png

// BasicDataSource实现了IDataSource接口,用于管理listener监听,以及通知LazyForEach数据更新

// ------ class BasicDataSource这个名是自定义的 -------
class BasicDataSource implements IDataSource {

// ------ DataChangeListener上面提到必须使用的对象 -------
  private listeners: DataChangeListener[] = [];
  
// ------ 你要懒加载的数据 -------
  private originDataArray: string[] = [];


// --------- 必须定义,否则报错 -------------------
// ------ 懒加载的数据的长度(必填否则报错:接口要求) -------
  public totalCount(): number {
    return 0;
  }

//  ------ 传index,返回当前数据(必填否则报错:接口要求) -------
  public getData(index: number): string {
    return this.originDataArray[index];
  }

接下来的代码一般情况下,就直接复制即可,有为框架服务的方法(必填)以及封装好让你调用的方法。

注意:数据更新是用this.listeners.方法,这样用才能更新数据。直接去操作我们传的数据,数据会变UI不变。简单来说,如果我们更新数据的同时要更新UI,一般情况下调用那些封装好的方法即可。

image.png

//------------------------------------------------------------------
// ------------------- 以下方法将自动调用,为框架服务的方法(必须定义,接口要求) ---------------------
// ---------(下面两个实现更新用的,一般直接复制就可以了)-------
  // 该方法为框架侧调用,为LazyForEach组件向其数据源处添加listener监听
  registerDataChangeListener(listener: DataChangeListener): void {
    if (this.listeners.indexOf(listener) < 0) {
      console.info('add listener');
      this.listeners.push(listener);
    }
  }

  // 该方法为框架侧调用,为对应的LazyForEach组件在数据源处去除listener监听
  unregisterDataChangeListener(listener: DataChangeListener): void {
    const pos = this.listeners.indexOf(listener);
    if (pos >= 0) {
      console.info('remove listener');
      this.listeners.splice(pos, 1);
    }
  }

//------------------------------------------------------------------
// ------------------- 以下方法是数据更新,提供给大家调用的---------------------
// ----------- 封装好的,触发更新的方法,一般不需要动,直接复制按需调用 --------------
// -------------------- 想要UI变化,就会调用到这些方法  ------------
  // 通知LazyForEach组件需要重载所有子组件(所有数据发生变化,调用这个)
  notifyDataReload(): void {
    this.listeners.forEach(listener => {
      listener.onDataReloaded();
    })
  }

  // 通知LazyForEach组件需要在index对应索引处添加子组件(只是新增一个数据,调用这个)
  notifyDataAdd(index: number): void {
    this.listeners.forEach(listener => {
      listener.onDataAdd(index);
      // 写法2:listener.onDatasetChange([{type: DataOperationType.ADD, index: index}]);
    })
  }

  // 通知LazyForEach组件在index对应索引处数据有变化,需要重建该子组件(某个数据内容发生变化,调用这个)
  notifyDataChange(index: number): void {
    this.listeners.forEach(listener => {
      listener.onDataChange(index);
      // 写法2:listener.onDatasetChange([{type: DataOperationType.CHANGE, index: index}]);
    })
  }

  // 通知LazyForEach组件需要在index对应索引处删除该子组件(删除数据,调用这个)
  notifyDataDelete(index: number): void {
    this.listeners.forEach(listener => {
      listener.onDataDelete(index);
      // 写法2:listener.onDatasetChange([{type: DataOperationType.DELETE, index: index}]);
    })
  }

  // 通知LazyForEach组件将from索引和to索引处的子组件进行交换(数据移动,调用这个)
  notifyDataMove(from: number, to: number): void {
    this.listeners.forEach(listener => {
      listener.onDataMove(from, to);
      // 写法2:listener.onDatasetChange(
      //         [{type: DataOperationType.EXCHANGE, index: {start: from, end: to}}]);
    })
  }

  notifyDatasetChange(operations: DataOperation[]): void {
    this.listeners.forEach(listener => {
      listener.onDatasetChange(operations);
    })
  }
}

代码很多,总结一下

LazyForEach:数据懒加载-渲染控制-学习ArkTS语言-基础入门 - 华为HarmonyOS开发者 (huawei.com) 简单来说,这个class类来实现我们的懒加载,它有两把钥匙

  • 一把是传进来的数据,需要有两个方法数据长度getdata
  • 一把是更新UI的必填的对象,以及两个ui更新方法:registerDataChangeListenerunregisterDataChangeListener。这几个都是必填的,也就是四个方法两个数据。
  • 后面的UI更新方法,用于调用更新UI,如果不用而直接操作数据,数据会变,而UI不变

开始实践,实践出真知

注意:必须要用ets后缀文件,里面用到了一些内容比如DataChangeListener对象,ets可以用ts,ts不用ets

为形成对比,下面会用同一个例子分别使用 forEachlazyforeach

foreach

这里就不多做解释,这是一个简单的forEach渲染的swiper

image.png image.png

lazyforeach

测试任务分为:

  1. 在原有数据上添加单个数据并更新UI(更新数据并更新UI)
  2. 在原有数据上添加单个数据不更新UI(只更新数据而不调用封装的UI方法)
  3. 更新数据UI (直接调用更新UI的方法)
  4. 将原有数据进行整体替换并更新UI(将原数据重新赋值,并更新UI)

第一步:官网给的代码拉过来,放到一个ets文件夹里去并抛出(只赋值还没操作)

image.png

第二步:页面引入建立实例,对懒加载类进行修改(将初始数据写入)

image.png image.png

第三步:对于我们的测试任务编写相对应的 方法

  1. 添加数据并更新UI:这里调用用了更新UI的方法中的notifyDataAdd(index)

image.png

  1. 添加数据但没有更新UI:也就是没有调用更新UI的方法(旨在与上面更新UI的情况进行对比)

image.png

3.重新给数据赋值,并更新UI

image.png

4.重新更新UI

image.png

第四步:方法写好,开始测试,为方便测试,写到了button里

image.png

第五步:测试结果

初始状态

image.png

更新数据和UI 按钮点击:数据被更新,页面也发生变化

image.png

数据重新赋值并更新UI:整个数据重新赋值并更新

image.png

仅更新数据:因为与上面的情况用的是一个数据,此测试是刷新后重来的。页面没有发生变化,但是此时数据已经发生改变。

(因为 基于数据更新UI 按钮的作用就是调用 UI更新方法去根据当前的数据进行重新的渲染,所以在此基础上,我们再点击 基于数据更新UI 按钮触发,就会将UI进行更新)

image.png

基于数据更新UI,基于上面的情况,点击后基于当前数据更新了UI

image.png

总结

鸿蒙开发中 懒加载的优化如何实现进行了介绍
首先是对实现的class类内容进行介绍主要包括:更新UI的对象,渲染数据,getdata方法,返回数据长度方法,提供给框架更新的两个方法(这些为必填)。和一些提供给开发者的UI更新方法
对于其实现,进行了简单测试主要是观察其 使用方式 以及其 使用或不使用UI更新的情况
结论相比起foreach使用起来更加的繁琐,但是其能够达到的效果(在视图就显示,不在视图范围就销毁)还是比较不错的,而懒加载作为前端开发的常用优化方法,还是要掌握的,同时当我们开始使用之后,其实还是没有那么复杂