HarmonyOS ArkTS 用户首选项的开发及测试

news2024/11/15 17:05:27

本节以一个“账本”为例,使用首选项的相关接口实现了对账单的增、删、改、查操作,并使用自动化测试框架arkxtest来对应用进行自动化测试。

为了演示该功能,创建一个名为“ArkTSPreferences”的应用。应用源码可以在文末《跟老卫学HarmonyOS开发》链接找到。

1. 操作Preferences

首先要获取一个Preferences来操作首选项。

src/main/ets目录下创建名为“common”目录,用于存放常用的工具类。在该common目录创建工具类PreferencesUtil,代码如下:

// 导入preferences模块
import { preferences } from '@kit.ArkData';

import { BusinessError } from '@kit.BasicServicesKit';
import { common } from '@kit.AbilityKit';


let context = getContext(this) as common.UIAbilityContext;
let options: preferences.Options = { name: 'myStore' };

export default class PreferencesUtil {
  private dataPreferences: preferences.Preferences | null = null;

  // 调用getPreferences方法读取指定首选项持久化文件,
  // 将数据加载到Preferences实例,用于数据操作
  async getPreferencesFromStorage() {
    await preferences.getPreferences(context, options).then((data) => {
      this.dataPreferences = data;
      console.info(`Succeeded in getting preferences`);
    }).catch((err: BusinessError) => {
      console.error(`Failed to get preferences, Cause:` + err);
    });
  }
}
复制

为了对数据进行保存、查询、删除查操作,我们要封装对应接口。首选项接口提供的保存、查询、删除方法均有callback和Promise两种异步回调方式,本例子使用了Promise异步回调。代码如下:

// 将用户输入的数据,保存到缓存的Preference实例中
async putPreference(key: string, data: string) {
  if (this.dataPreferences === null) {
    await this.getPreferencesFromStorage();
  } else {
    await this.dataPreferences.put(key, data).then(() => {
      console.info(`Succeeded in putting value`);
    }).catch((err: BusinessError) => {
      console.error(`Failed to get preferences, Cause:` + err);
    });

    // 将Preference实例存储到首选项持久化文件中
    await this.dataPreferences.flush();
  }
}

// 使用Preferences的get方法读取数据
async getPreference(key: string) {
  let result: string= '';
  if (this.dataPreferences === null) {
    await this.getPreferencesFromStorage();
  } else {
    await this.dataPreferences.get(key, '').then((data) => {
      result = data.toString();
      console.info(`Succeeded in getting value`);
    }).catch((err: BusinessError) => {
      console.error(`Failed to get preferences, Cause:` + err);
    });
  }

  return result;
}

// 从内存中移除指定文件对应的Preferences单实例。
// 移除Preferences单实例时,应用不允许再使用该实例进行数据操作,否则会出现数据一致性问题。
async deletePreferences() {

  preferences.deletePreferences(context, options, (err: BusinessError) => {
    if (err) {
      console.error(`Failed to delete preferences. Code:${err.code}, message:${err.message}`);
      return;
    }

    this.dataPreferences = null;
    console.info('Succeeded in deleting preferences.');
  })
}
复制
2. 账目信息的表示

在src/main/ets目录下创建名为“database”目录,并在该database目录下创建类AccountData,代码如下:

export default interface AccountData {
  id: number;
  accountType: number;
  typeText: string;
  amount: number;
}
复制

AccountData各属性含义如下:

  • id:主键。
  • accountType:账目类型。0表示支出;1表示收入。
  • typeText:账目的具体类别。
  • amount:账目金额。
3. 设计界面

为了简化程序,突出核心逻辑,我们的界面设计的非常简单,只是一个Text组件和四个Button组件。四个Button组件用于触发增、删、改、查操作,而Text组件用于展示每次操作后的结果。修改Index代码如下:

// 导入PreferencesUtil
import PreferencesUtil from '../common/PreferencesUtil';
// 导入AccountData
import AccountData from '../database/AccountData';

const PREFERENCES_KEY = 'fruit';

@Entry
@Component
struct Index {
  @State message: string = 'Hello World'
  private preferencesUtil = new PreferencesUtil();

  async aboutToAppear() {
    // 初始化首选项
    await this.preferencesUtil.getPreferencesFromStorage();

    // 获取结果
    this.preferencesUtil.getPreference(PREFERENCES_KEY).then(resultData => {
      this.message = resultData;
    });
  }

  build() {
    Row() {
      Column() {
        Text(this.message)
          .id('text_result')
          .fontSize(50)
          .fontWeight(FontWeight.Bold)

        // 增加
        Button(('增加'), { type: ButtonType.Capsule })
          .width(140)
          .fontSize(40)
          .fontWeight(FontWeight.Medium)
          .margin({ top: 20, bottom: 20 })
          .onClick(() => {
            // 保存数据
            let newAccount: AccountData = { id: 1, accountType: 0, typeText: '苹果', amount: 0 };
            this.preferencesUtil.putPreference(PREFERENCES_KEY, JSON.stringify(newAccount));
          })

        // 查询
        Button(('查询'), { type: ButtonType.Capsule })
          .width(140)
          .fontSize(40)
          .fontWeight(FontWeight.Medium)
          .margin({ top: 20, bottom: 20 })
          .onClick(() => {
            // 获取结果
            this.preferencesUtil.getPreference(PREFERENCES_KEY).then(resultData => {
              this.message = resultData;
            });
          })

        // 修改
        Button(('修改'), { type: ButtonType.Capsule })
          .width(140)
          .fontSize(40)
          .fontWeight(FontWeight.Medium)
          .margin({ top: 20, bottom: 20 })
          .onClick(() => {
            // 修改数据
            let newAccount: AccountData = { id: 1, accountType: 1, typeText: '栗子', amount: 1 };
            this.preferencesUtil.putPreference(PREFERENCES_KEY, JSON.stringify(newAccount));
          })

        // 删除
        Button(('删除'), { type: ButtonType.Capsule })
          .width(140)
          .fontSize(40)
          .fontWeight(FontWeight.Medium)
          .margin({ top: 20, bottom: 20 })
          .onClick(() => {
            this.preferencesUtil.deletePreferences();
          })
      }
      .width('100%')
    }
    .height('100%')
  }
}
复制

上述代码,在aboutToAppear生命周期阶段,初始化了Preferences。点击“新增”会将预设好的数据“{ id: 1, accountType: 0, typeText: '苹果', amount: 0 }”写入到Preferences。点击“修改”会将预设好的“{ id: 1, accountType: 1, typeText: '栗子', amount: 1 }”的数据更新到Preferences。点击“删除”则会从内存中移除指定文件对应的Preferences单实例。

4. 运行

运行应用显示的界面效果如下图所示。

图10-8 界面效果

当用户点击“增加”后再点击“查询”时,界面如下图所示,证明数据已经成功写入Preferences。

图10-9 数据已经成功写入Preferences

当用户点击“修改”后再点击“查询”时,界面如下图所示,证明数据已经被修改并更新回Preferences。

图10-10 数据已经被修改并更新回Preferences

当用户点击“删除”后再点击“查询”时,界面如下图所示,证明数据已经从Preferences删除。

图10-11 数据已经从Preferences删除

5. 编写UI测试脚本

UI测试基于单元测试,UI测试脚本在单元测试脚本上增加了对UiTest接口,具体请参考API文档。

如下的示例代码是在上面的单元测试脚本基础上增量编写,实现的是在启动的应用页面上进行点击操作,然后检测当前页面变化是否为预期变化。

在“ohosTest/ets/test/”目录下,是专门用于存放具体测试代码的。在该目录下,已经存在了一个测试用例样板代码Ability.test.ets文件,基于该文件进行编写UI测试脚本。修改后,代码如下:

import { describe, it, expect } from '@ohos/hypium';
import { abilityDelegatorRegistry, Driver, ON } from '@kit.TestKit';
import { UIAbility, Want } from '@kit.AbilityKit';
import AccountData from '../../../main/ets/database/AccountData';

const delegator: abilityDelegatorRegistry.AbilityDelegator = abilityDelegatorRegistry.getAbilityDelegator()
const bundleName = abilityDelegatorRegistry.getArguments().bundleName;

function sleep(time: number) {
  return new Promise<void>((resolve: Function) => setTimeout(resolve, time));
}

export default function abilityTest() {
  describe('ActsAbilityTest', () => {

    // 编写UI测试脚本
    it('testUi',0, async (done: Function) => {
      console.info("uitest: testUi begin");
      // 启动待测试的 ability
      const want: Want = {
        bundleName: bundleName,
        abilityName: 'EntryAbility'
      }
      await delegator.startAbility(want);
      await sleep(1000);

      // 检查顶层显示的 ability
      await delegator.getCurrentTopAbility().then((Ability: UIAbility)=>{
        console.info("get top ability");
        expect(Ability.context.abilityInfo.name).assertEqual('EntryAbility');
      })

      // UI 测试代码
      // 初始化driver
      let driver = Driver.create();
      await driver.delayMs(1000);

      // 查找'增加'按钮
      let buttonAdd = await driver.findComponent(ON.text('增加'));

      // 点击按钮
      await buttonAdd.click();
      await driver.delayMs(1000);

      // 查找'查询'按钮
      let buttonQuery = await driver.findComponent(ON.text('查询'));

      // 点击按钮
      await buttonQuery.click();
      await driver.delayMs(1000);

      // 查找 id 为'text_result'的 Text 组件
      let text = await driver.findComponent(ON.id('text_result'));

      // 检查文本内容
      await text.getText().then(result => {
        let newAccount: AccountData = { id: 1, accountType: 0, typeText: '苹果', amount: 0 };

        expect(result).assertEqual(JSON.stringify(newAccount))
      });

      done();
    })

  })
}
复制

上述代码主要做了以下几件事:

  • 查找增加按钮,并进行点击;
  • 查找查询按钮,并进行点击;
  • 查找Text组件,断言该Text组件文本内容是否与期望的值一致。
6. 运行UI测试脚本

首先,启动模拟器或者真机。在模拟器或者真机上安装应用。

其次,点击如下图13-1所示的测试用例的左侧三角按钮,以运行测试脚本。

图13-1 测试脚本执行按钮

如果断言成功,则说明测试通过,可以看到如下绿色打勾的标识。

图13-2 测试用例断言成功

如果断言失败,则说明测试没有通过,可以看到如下红色告警标识,并会提示断言失败的原因。

图13-3 测试用例断言失败

7. 参考
  • 《跟老卫学HarmonyOS开发》 开源免费教程,GitHub - waylau/harmonyos-tutorial: HarmonyOS Tutorial. 《跟老卫学HarmonyOS开发》
  • 《鸿蒙HarmonyOS手机应用开发实战》(清华大学出版社)
  • 《鸿蒙HarmonyOS应用开发从入门到精通战》(北京大学出版社)
  • “鸿蒙系统实战短视频App 从0到1掌握HarmonyOS”(鸿蒙系统实战短视频App 从0到1掌握HarmonyOS_实战课程_慕课网)
  • 《鸿蒙HarmonyOS应用开发入门》(清华大学出版社)
  • “2024鸿蒙零基础快速实战-仿抖音App开发(ArkTS版)”(2024 鸿蒙零基础快速实战-仿抖音App开发( ArkTS版 )_实战课程_慕课网)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

恢复已删除文件的可行方法,如何恢复已删除的文件

在清理 PC 或优化存储设备时无意中删除重要文件是一种常见的人为错误。不可否认&#xff0c;在批量删除文件时&#xff0c;您通常会一起删除垃圾文件和重要文件。您后来意识到一堆文件或文件中缺少一个重要的文档或文件。在这种情况下&#xff0c;您唯一的选择是寻找恢复已删除…

优思学院|如何通过六西格玛方法优化流程,减少90%的浪费?

随着竞争压力的增加和对更快结果的需求&#xff0c;越来越多的企业开始依赖精益六西格玛来优化流程&#xff0c;减少浪费。精益六西格玛不仅改变了制造业&#xff0c;也影响了几乎所有行业的业务运营&#xff0c;提升了效率&#xff0c;消除了低效环节。这里优思学院和大家探讨…

sheng的学习笔记-AI-强化学习(Reinforcement Learning, RL)

AI目录&#xff1a;sheng的学习笔记-AI目录-CSDN博客 基础知识 什么是强化学习 强化学习&#xff08;Reinforcement Learning, RL&#xff09;&#xff0c;又称再励学习、评价学习或增强学习&#xff0c;是机器学习的范式和方法论之一&#xff0c;用于描述和解决智能体&#…

电机设计及电机仿真APP系列之—高速永磁同步电机仿真APP

电机的各种工作状态和参数变化。用户可通过调整仿真参数&#xff0c;快速得到电机的响应和性能参数&#xff0c;从而进行针对性的优化和改进。借助仿真APP&#xff0c;可大大减少电机设计迭代次数和成本&#xff0c;提高测试效率和准确性。 小编整理了10款不同类型的电机仿真A…

掌握顶会流量密码!“Mamba+CNN”双热点组合!轻松找到创新点!

传统视觉模型在处理大规模或高分辨率图像时存在一定限制。然而Mamba与CNN相结合&#xff0c;在处理序列数据和图像数据时有着显著的优势&#xff0c;并且能够有效提升模型计算效率和准确率。 这种结合可以让Mamba在处理长序列数据时既能够捕捉到序列中的时间依赖关系&#xff…

springboot整合springbatch和xxljob实现定时数据同步(完整代码)

springboot整合springbatch和xxljob实现定时数据同步&#xff08;完整代码&#xff09; 前言&#xff1a;公司一些老项目的定时任务使用spring自带的调度器来完成数据同步的&#xff0c;久而久之带来很多的不方便。首先没办法快速定位监控定时任务的执行情况&#xff0c;其次就…

c++11右值引用和移动语义

一.左值引用和右值引用 什么是左值引用&#xff0c;什么是右值引用 左值是一个表示数据的表达式&#xff08;变量名解引用的指针&#xff09;&#xff0c;我们可以获取到它的地址&#xff0c;可以对它赋值&#xff0c;左值可以出现在符号的左边。使用const修饰后&#xff0c;…

python检测keycloak证书连接报错问题

最近一直被keycloak的证书问题困扰了很久&#xff0c;老是提示ssl安全连接&#xff0c;由于不会java,只好硬着头皮用python测试。 我这里的证书是自己签注的证书&#xff0c;导入系统的是CA根证书。 from keycloak import KeycloakOpenID# 1. 配置 Keycloak 客户端 keycloak_o…

电子画册3D翻页电子版是如何制作

​随着科技的发展&#xff0c;传统的纸质画册逐渐被电子画册所取代。电子画册3D翻页电子版以其独特的交互方式和丰富的视觉体验&#xff0c;受到了越来越多人的喜爱。让我来教你怎么制作吧。 1.要制作电子杂志,首先需要选择一款适合自己的软件。比如FLBOOK在线制作电子杂志平台…

信息收集常用指令

目的 本文主要是记录一些在信息搜集时&#xff0c;常用的提高搜索效率的命令。 后续会继续记录一些用到的更多指令和方法&#xff0c;慢慢更新。 1、inurl “inurl:xxx”是指查找url中包含xxx的网页。 URL&#xff1a;统一资源定位符。统一资源定位系统。可以说包含域名&am…

ThreaLocal

1.概述 ThreadLoca称线程局部变量&#xff0c;用于在线程中保存数据&#xff0c;保存的数据仅属于当前线程(即对其他线程而言&#xff0c;该变量是当前线程独有的变量) threadLocal利用Thread中的ThreadLocalMap来进行数据存储 2.常用方法 存储数据至当前线程ThreadLocalMap中…

无监督神经组合优化的扩散模型框架

文章目录 Abstract1. Introduction2. Problem Description2.1 无监督神经组合优化3. Neural Probabilistic Optimization Objective for Approximate Likelihood Models3.1 具有联合变分上界的训练扩散模型Abstract 从离散集合的不可处理分布中进行采样,而不依赖相应的训练数据…

OpenAI o1解决了Quiet-STaR的挑战吗?(下)

随着OpenAI o1近期的发布&#xff0c;业界讨论o1关联论文最多之一可能是早前这篇斯坦福大学和Notbad AI Inc的研究人员开发的Quiet-STaR&#xff0c;即让AI学会先安静的“思考”再“说话” &#xff0c;回想自己一年前对于这一领域的思考和探索&#xff0c;当初也将这篇论文进行…

初学者蒙语学习,使用什么翻译软件学习更快?

为了加快蒙古语的学习&#xff0c;初学者应该从基础语法和词汇入手&#xff0c;利用语言学习应用进行系统学习&#xff0c;并通过音频和视频材料提高听力。语言交换和参加课程可以提供实践机会&#xff0c;而使用闪卡和文化沉浸有助于记忆词汇和理解语言背景。定期复习和设定学…

聊天组件 Vue3-beautiful-chat 插槽

前言 Vue3-beautiful-chat 组件有四个插槽可以定制 一、user-avatar(头像) 首先是头像插槽,我们可以直接在 <beautiful-chat></beautiful-chat> 中间使用; 作用: 我们可以在用户头像上添加自定义样式,比如添加节日边框、可以使用首字母作为头像。。。 …

小阿轩yx-通过state模块定义主机状态

小阿轩yx-通过state模块定义主机状态 前言 前面学习了远程执行模块&#xff0c;这些模块的执行类似语段 shell 脚本&#xff0c;每次执行都会触发一次相同的功能&#xff0c;在大量的 minion 上运行远程命令当然是重要的&#xff0c;但是对于 minion 的环境控制&#xff0c;使…

Python 二级考试

易错点 定义学生关系模式如下&#xff1a;Student &#xff08;S#&#xff0c; Sn&#xff0c; Ssex&#xff0c;class&#xff0c;monitorS#&#xff09;&#xff08;其属性分别为学号、学生名、性别、班级和班长学号&#xff09; 在关系模式中&#xff0c;如果Y -> X&…

超详细!百分百安装成功pytorch,建议收藏

文章目录 一、Anaconda安装1.1下载anaconda1.2配置Anaconda环境1.3验证anaconda是否安装成功 二、查看电脑显卡三、更新显卡驱动3.1下载驱动3.2、查看显卡驱动版本 四、cuda安装4.1CUDA下载4.2CUDA环境配置4.3验证CUDA是否安装成功 五、安装pytorch4.1下载pytorch5.2验证pytorc…

计算机专业的就业方向

计算机专业的就业方向 亲爱的新生们&#xff0c;欢迎你们踏上计算机科学的旅程&#xff01;作为一名计算机专业的学生&#xff0c;你们即将进入一个充满无限可能的领域。今天&#xff0c;我将为大家介绍计算机专业的一些主要就业方向&#xff0c;帮助你们了解未来的职业选择。…

备忘录应用哪些值得推荐?优秀的桌面备忘录下载

在我们的日常生活和工作中&#xff0c;备忘录是一款常用的记录软件&#xff0c;它为我们提供了极大的便利&#xff0c;让我们可以随时记录下重要的信息、灵感和待办事项。然而&#xff0c;如今网上的备忘录软件琳琅满目&#xff0c;究竟哪一款才是真正优秀的呢&#xff1f; 在…