一、LazyForEach: 数据懒加载

LazyForEach必须在容器组件内使用,仅有List、Grid、Swiper以及WaterFlow组件支持数据懒加载(可配置cachedCount属性,即只加载可视部分以及其前后少量数据用于缓冲),其他组件仍然是一次性加载所有的数据。支持数据懒加载的父组件根据自身及子组件的高度或宽度计算可视区域内需布局的子节点数量,高度或宽度的缺失会导致部分场景懒加载失效。

List设置cachedCount后,显示区域外上下各会预加载并布局cachedCount行ListItem。计算ListItem行数时,会计算ListItemGroup内部的ListItem行数。如果ListItemGroup内没有ListItem,则整个ListItemGroup算一行。

List下嵌套使用LazyForEach,并且LazyForEach下嵌套使用ListItemGroup时,LazyForEach会在List显示区域外上下各会创建cachedCount个ListItemGroup。

二、ohos.data.preferences (用户首选项)

getPreferences(context: Context, name: string): Promise
获取Preferences实例,使用Promise异步回调。

getPreferences(context: Context, options: Options, callback: AsyncCallback): void
获取Preferences实例,使用callback异步回调。

getPreferencesSync(context: Context, options: Options): Preferences
获取Preferences实例,此为同步接口

三、@Builder装饰器:自定义构建函数

装饰器使用说明
@Builder装饰器有两种使用方式,分别是定义在自定义组件内部的私有自定义构建函数和定义在全局的全局自定义构建函数。

使用方法
允许在自定义组件内定义一个或多个@Builder函数,该函数被认为是该组件的私有、特殊类型的成员函数。

私有自定义构建函数允许在自定义组件内、build函数和其他自定义构建函数中调用。

在自定义组件中,this指代当前所属组件,组件的状态变量可在自定义构建函数内访问。建议通过this访问组件的状态变量,而不是通过参数传递。

四、User-Agent开发指导

通过setCustomUserAgent()接口设置自定义用户代理,但请注意,此操作会覆盖系统的用户代理。因此,我们建议将扩展字段追加在默认用户代理的末尾,比如三方应用程序的开发场景,可以在系统默认用户代理字符串的末尾追加特定的APP标识,这样既能保留原有用户代理信息,又能增加自定义的应用识别信息。

当Web组件src设置了url时,建议在onControllerAttached回调事件中设置User-Agent,设置方式请参考示例。不建议将User-Agent设置在onLoadIntercept回调事件中,会概率性出现设置失败。如果未在onControllerAttached回调事件中设置User-Agent。再调用setCustomUserAgent方法时,可能会出现加载的页面与实际设置User-Agent不符的异常现象。

当Web组件src设置为空字符串时,建议先调用setCustomUserAgent方法设置User-Agent,再通过loadUrl加载具体页面。

五、Profile Manager

在Create Profile界面,填写新增设备的信息,如Profile ID(设备型号)、Device type(设备类型)、Resolution(分辨率)和Language and region(语言和区域)等。其中Device type只能选择module.json5中deviceTypes字段已定义的设备。
在这里插入图片描述

六、UIAbility组件启动模式

  • singleton(单实例模式)
  • multiton(多实例模式)
  • specified(指定实例模式)

说明
standard是multiton的曾用名,效果与多实例模式一致。

如果需要使用singleton启动模式,在module.json5配置文件中的launchType字段配置为singleton即可。

{
  "module": {
    // ...
    "abilities": [
      {
        "launchType": "singleton",
        // ...
      }
    ]
  }
}

multiton启动模式为多实例模式,每次调用startAbility()方法时,都会在应用进程中创建一个新的该类型UIAbility实例。即在最近任务列表中可以看到有多个该类型的UIAbility实例。这种情况下可以将UIAbility配置为multiton(多实例模式)。

specified启动模式
specified启动模式为指定实例模式,针对一些特殊场景使用(例如文档应用中每次新建文档希望都能新建一个文档实例,重复打开一个已保存的文档希望打开的都是同一个文档实例)。
在这里插入图片描述

七、HTTP数据请求

设置请求方式 支持GET、POST、HEAD、PUT、DELETE、TRACE、CONNECT、OPTIONS方法,默认为GET

1.创建HttpRequest对象
调用createHttp()方法,创建HttpRequest对象。
提醒:每一个httpRequest对应一个HTTP请求任务,不可复用。

let context: common.UIAbilityContext = this.getUIContext().getHostContext() as common.UIAbilityContext;
// 每一个httpRequest对应一个HTTP请求任务,不可复用。
let httpRequest = http.createHttp();

2.订阅HTTP响应头事件
调用该对象的on()方法,订阅HTTP响应头事件,此接口会比request请求先返回。可以根据业务需要订阅此消息。

// 用于订阅HTTP响应头,此接口会比request请求先返回。可以根据业务需要订阅此消息。
// 从API 8开始,使用on('headersReceive', Callback)替代on('headerReceive', AsyncCallback)。
httpRequest.on('headersReceive', (header) => {
  console.info('header: ' + JSON.stringify(header));
});

3.发起HTTP请求,解析服务器响应事件
调用该对象的request()方法,传入HTTP请求的url地址和可选参数,发起网络请求,按照实际业务需要,解析返回结果。

httpRequest.request(
  // 填写HTTP请求的URL地址,可以带参数或不带参数。URL地址由开发者自定义。请求的参数可以在extraData中指定。
  "EXAMPLE_URL",
  {
    method: http.RequestMethod.POST, // 可选,默认为http.RequestMethod.GET,用于从服务器获取数据,而POST方法用于向服务器上传数据。
    // 开发者根据自身业务需要添加header字段。
    header: {
      'Content-Type': 'application/json'
    },
    // 当使用POST请求时此字段用于传递请求体内容,具体格式与服务端协商确定。
    extraData: "data to send",
    expectDataType: http.HttpDataType.STRING, // 可选,指定返回数据的类型。
    usingCache: true, // 可选,默认为true。
    priority: 1, // 可选,默认为1。
    connectTimeout: 60000, // 可选,默认为60000ms。
    readTimeout: 60000, // 可选,默认为60000ms。
    usingProtocol: http.HttpProtocol.HTTP1_1, // 可选,协议类型默认值由系统自动指定。
    usingProxy: false, // 可选,默认不使用网络代理,自API 10开始支持该属性。
    caPath:'/path/to/cacert.pem', // 可选,默认使用系统预制证书,自API 10开始支持该属性。
    clientCert: { // 可选,默认不使用客户端证书,自API 11开始支持该属性。
      certPath: '/path/to/client.pem', // 默认不使用客户端证书,自API 11开始支持该属性。
      keyPath: '/path/to/client.key', // 若证书包含Key信息,传入空字符串,自API 11开始支持该属性。
      certType: http.CertType.PEM, // 可选,默认使用PEM,自API 11开始支持该属性。
      keyPassword: "passwordToKey" // 可选,输入key文件的密码,自API 11开始支持该属性。
    },
    multiFormDataList: [ // 可选,仅当Header中,'content-Type'为'multipart/form-data'时生效,自API 11开始支持该属性,该属性用于支持向服务器上传二进制数据,根据上传的具体数据类型进行选择。
      {
        name: "Part1", // 数据名,自API 11开始支持该属性。
        contentType: 'text/plain', // 数据类型,自API 11开始支持该属性,上传的数据类型为普通文本文件。
        data: 'Example data', // 可选,数据内容,自API 11开始支持该属性。
        remoteFileName: 'example.txt' // 可选,自API 11开始支持该属性。
      }, {
        name: "Part2", // 数据名,自API 11开始支持该属性。
        contentType: 'text/plain', // 数据类型,自API 11开始支持该属性,上传的数据类型为普通文本文件。
        // data/app/el2/100/base/com.example.myapplication/haps/entry/files/fileName.txt。
        filePath: `${context.filesDir}/fileName.txt`, // 可选,传入文件路径,自API 11开始支持该属性。
        remoteFileName: 'fileName.txt' // 可选,自API 11开始支持该属性。
      }, {
        name: "Part3", // 数据名,自API 11开始支持该属性。
        contentType: 'image/png', // 数据类型,自API 11开始支持该属性,上传的数据类型为png格式的图片。
        // data/app/el2/100/base/com.example.myapplication/haps/entry/files/fileName.png。
        filePath: `${context.filesDir}/fileName.png`, // 可选,传入文件路径,自API 11开始支持该属性。
        remoteFileName: 'fileName.png' // 可选,自API 11开始支持该属性。
      }, {
        name: "Part4", // 数据名,自API 11开始支持该属性。
        contentType: 'audio/mpeg', // 数据类型,自API 11开始支持该属性,上传的数据类型为mpeg格式的音频。
        // data/app/el2/100/base/com.example.myapplication/haps/entry/files/fileName.mpeg。
        filePath: `${context.filesDir}/fileName.mpeg`, // 可选,传入文件路径,自API 11开始支持该属性。
        remoteFileName: 'fileName.mpeg' // 可选,自API 11开始支持该属性。
      }, {
        name: "Part5", // 数据名,自API 11开始支持该属性。
        contentType: 'video/mp4', // 数据类型,自API 11开始支持该属性,上传的数据类型为mp4格式的视频。
        // data/app/el2/100/base/com.example.myapplication/haps/entry/files/fileName.mp4。
        filePath: `${context.filesDir}/fileName.mp4`, // 可选,传入文件路径,自API 11开始支持该属性。
        remoteFileName: 'fileName.mp4' // 可选,自API 11开始支持该属性。
      }
    ]
  }, (err: BusinessError, data: http.HttpResponse) => {
    if (!err) {
      // data.result为HTTP响应内容,可根据业务需要进行解析。
      console.info('Result:' + JSON.stringify(data.result));
      console.info('code:' + JSON.stringify(data.responseCode));
      // data.header为HTTP响应头,可根据业务需要进行解析。
      console.info('header:' + JSON.stringify(data.header));
      console.info('cookies:' + JSON.stringify(data.cookies)); // 8+
      // 当该请求使用完毕时,调用destroy方法主动销毁。
      httpRequest.destroy();
    } else {
      console.error('error:' + JSON.stringify(err));
      // 取消订阅HTTP响应头事件。
      httpRequest.off('headersReceive');
      // 当该请求使用完毕时,调用destroy方法主动销毁。
      httpRequest.destroy();
    }
  }
);

八、RichEditor

九、安全控件通用属性

markAnchor(value: Position): T
设置安全控件在位置定位时的锚点,以控件左上角作为基准点进行偏移。

十、背景设置

backgroundBrightness(params: BackgroundBrightnessOptions): T
设置组件背景提亮效果。
BackgroundBrightnessOptions:设置组件背景提亮效果,包括:亮度变化速率,提亮程度。

十一、多设备交互

焦点导航事件适配

使用键盘、电视遥控器、车机摇杆或旋钮等非指向性输入设备与应用程序进行间接交互时,建议将页面中可操作元素设置为可获焦状态,并配置获焦视觉效果,以保证交互体验。

  • 获焦:组件获焦时,遵循子组件优先原则。若子组件需获焦,其所有祖先组件均需可获焦。容器组件需获焦时,其子组件应不可获焦,并配置点击事件。
    部分组件默认可获焦,如Button、TextInput等基础组件和Column、Row等容器组件。若组件有获焦能力但默认不可获焦,如Text、Image等组件,可设置通用属性focusable(true)使其可获焦。
  • 走焦:触发走焦时,系统遍历组件树中可走焦的组件。不同按键触发不同的走焦逻辑。例如,TAB键走焦遵循Z字型遍历逻辑;方向键走焦遵循十字型移动逻辑。除了系统默认的走焦逻辑,开发者可以通过tabIndex自定义走焦逻辑。

十二、应用上下文Context

el1与el2文件之间的区别

三级目录el1/和el2/:代表不同文件加密类型。

el1(设备级加密区):设备开机后可访问的数据区。

el2(用户级加密区):设备开机后,需解锁对应用户的锁屏界面(密码、指纹、人脸等方式或无密码状态)至少一次,才能访问加密数据区。

应用若无特殊需求,应将数据存放在EL2加密目录下,以保障数据安全。对于需要在用户解锁前访问的文件,如时钟、闹铃、壁纸等,应将这些文件存放在设备级加密区(EL1)。

获取和修改加密分区

应用文件加密是一种保护数据安全的方法,可以使得文件在未经授权访问的情况下得到保护。在不同的场景下,应用需要不同程度的文件保护。

在实际应用中,开发者需要根据不同场景的需求选择合适的加密分区,从而保护应用数据的安全。通过合理使用不同级别的加密分区,可以有效提升应用数据的安全性。关于不同分区的权限说明,详见ContextConstant的AreaMode。

  • EL1:对于私有文件,如闹铃、壁纸等,应用可以将这些文件放到设备级加密分区(EL1)中,以保证在用户输入密码前就可以被访问。
  • EL2:对于更敏感的文件,如个人隐私信息等,应用可以将这些文件放到更高级别的加密分区(EL2)中,以保证更高的安全性。
  • EL3:对于应用中的记录步数、文件下载、音乐播放,需要在锁屏时读写和创建新文件,放在(EL3)的加密分区比较合适。
  • EL4:对于用户安全信息相关的文件,锁屏时不需要读写文件、也不能创建文件,放在(EL4)的加密分区更合适。
  • EL5:对于用户隐私敏感数据文件,锁屏后默认不可读写,如果锁屏后需要读写文件,则锁屏前可以调用Access接口申请继续读写文件,或者锁屏后也需要创建新文件且可读写,放在(EL5)的应用级加密分区更合适。

要实现获取和设置当前加密分区,可以通过读写Context的area属性来实现。

// EntryAbility.ets
import { UIAbility, contextConstant, AbilityConstant, Want } from '@kit.AbilityKit';

export default class EntryAbility extends UIAbility {
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
    // 存储普通信息前,切换到EL1设备级加密
    this.context.area = contextConstant.AreaMode.EL1; // 切换area
    // 存储普通信息

    // 存储敏感信息前,切换到EL2用户级加密
    this.context.area = contextConstant.AreaMode.EL2; // 切换area
    // 存储敏感信息

    // 存储敏感信息前,切换到EL3用户级加密
    this.context.area = contextConstant.AreaMode.EL3; // 切换area
    // 存储敏感信息

    // 存储敏感信息前,切换到EL4用户级加密
    this.context.area = contextConstant.AreaMode.EL4; // 切换area
    // 存储敏感信息

    // 存储敏感信息前,切换到EL5应用级加密
    this.context.area = contextConstant.AreaMode.EL5; // 切换area
    // 存储敏感信息
  }
}
// Index.ets
import { contextConstant, common } from '@kit.AbilityKit';

@Entry
@Component
struct Page_Context {
  private context = this.getUIContext().getHostContext() as common.UIAbilityContext;

  build() {
    Column() {
      //...
      List({ initialIndex: 0 }) {
        //...
        ListItem() {
          Row() {
            //...
          }
          .onClick(() => {
            // 存储普通信息前,切换到EL1设备级加密
            if (this.context.area === contextConstant.AreaMode.EL2) { // 获取area
              this.context.area = contextConstant.AreaMode.EL1; // 修改area
              this.getUIContext().getPromptAction().showToast({
                message: 'SwitchToEL1'
              });
            }
            // 存储普通信息
          })
        }
        //...
        ListItem() {
          Row() {
            //...
          }
          .onClick(() => {
            // 存储敏感信息前,切换到EL2用户级加密
            if (this.context.area === contextConstant.AreaMode.EL1) { // 获取area
              this.context.area = contextConstant.AreaMode.EL2; // 修改area
              this.getUIContext().getPromptAction().showToast({
                message: 'SwitchToEL2'
              });
            }
            // 存储敏感信息
          })
        }
        //...
      }
      //...
    }
    //...
  }
}

十三、image

object-fit 类型说明

类型 描述
cover 保持宽高比进行缩小或者放大,使得图片两边都大于或等于显示边界,居中显示。
contain 保持宽高比进行缩小或者放大,使得图片完全显示在显示边界内,居中显示。
fill 不保持宽高比进行放大缩小,使得图片填充满显示边界。
none 保持原有尺寸进行居中显示。
scale-down 保持宽高比居中显示,图片缩小或者保持不变。
Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐