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

本节以一个“账本”为例,使用首选项的相关接口实现了对账单的增、删、改、查操作,并使用自动化测试框架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");// 启动待测试的 abilityconst want: Want = {bundleName: bundleName,abilityName: 'EntryAbility'}await delegator.startAbility(want);await sleep(1000);// 检查顶层显示的 abilityawait delegator.getCurrentTopAbility().then((Ability: UIAbility)=>{console.info("get top ability");expect(Ability.context.abilityInfo.name).assertEqual('EntryAbility');})// UI 测试代码// 初始化driverlet 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.xdnf.cn/news/144114.html

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

相关文章

【齐家网-注册/登录安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞…

医学数据分析实训 项目十 基于深度残差神经网络的皮肤癌检测

文章目录 综合实践三 基于深度残差神经网络的皮肤癌检测实现步骤1&#xff1a;图像数据预处理实现步骤2&#xff1a;模型构建实现步骤3&#xff1a;性能度量提交要求 1 基于深度残差神经网络的皮肤癌检测代码2 结果分析 综合实践三 基于深度残差神经网络的皮肤癌检测 皮肤镜图…

毕业设计选题:基于ssm+vue+uniapp的校园商铺系统小程序

开发语言&#xff1a;Java框架&#xff1a;ssmuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;M…

828华为云征文 | 在华为云X实例上部署微服务架构的文物大数据管理平台的实践

前言 文物大数据管理平台的需求日益增长&#xff0c;要求系统具备强大的数据存储、智能查询和数据分析功能。通过微服务架构&#xff0c;平台可以灵活地管理用户、文件存储、文物知识、资源管理以及报表统计等模块。本文将以实际案例为基础&#xff0c;详细介绍如何在华为云Fl…

实现西门子PLC与发那科机器人通讯接收正负值偏移

PLC与发那科机器人通讯组信号的无法接受负数&#xff0c;并且高低字节取反&#xff1b; 解决办法如下&#xff1a; 在发送数据时双方约定一个基数&#xff0c;通讯时双方上这个值&#xff0c;或减去这个值即可&#xff1b; 如下图&#xff0c;当前约定收发数据范围为-20到20之…

【2024】前端学习笔记8-内外边距-边框-背景

学习笔记 外边距&#xff1a;Margin内边距&#xff1a;Padding边框&#xff1a;Border背景&#xff1a;Background 外边距&#xff1a;Margin 用于控制元素周围的空间&#xff0c;它在元素边框之外创建空白区域&#xff0c;可用于调整元素与相邻元素&#xff08;包括父元素和兄…

ORCA-3D避障代码和原理解析

二维ORCA原理参考&#xff1a; https://zhuanlan.zhihu.com/p/669426124 ORCA原理图解代码解释 1. 找到避障速度增量 u 碰撞处理分为三种情况&#xff1a; &#xff08;1&#xff09;没有发生碰撞&#xff0c;且相对速度落在小圆里 &#xff08;2&#xff09;没有发生碰撞&a…

蓝星多面体foc旋钮键盘复刻问题详解

介绍&#xff1a; 本教程是针对立创开源项目 承载我所有幻想的键盘 - 立创开源硬件平台 作者是 蓝星多面体 这里我总结一下我复刻过程中的一些问题 一 <<编译环境怎么搭建&#xff1f;>> 第一步 安装vscode 下载vscode &#xff08;可以在各大应用平台…

如何删除EXCELL文件中的空行?

1&#xff0c;选择某一列 2&#xff0c;点击《开始》《查找和选择》>《定位条件》&#xff0c;调出《定位条件》的选择框&#xff1b; 3&#xff0c;在定位条件选项框&#xff0c;选择《空值》&#xff1b; 4&#xff0c;找到变灰被选中的某一行&#xff0c;右击《删除》 5&…

高级算法设计与分析 学习笔记6 B树

B树定义 一个块里面存了1000个数和1001个指针&#xff0c;指针指向的那个块里面的数据大小介于指针旁边的两个数之间 标准定义&#xff1a; B树上的操作 查找B树 创建B树 分割节点 都是选择正中间的那个&#xff0c;以免一直分裂。 插入数字 在插入的路上就会检查节点需不需要…

Qt 类型选择器和类选择器的区别

概念上的区别请查看此篇博客&#xff1a;Qt 样式表、选择器、盒子模型&#xff0c;下面我直接举例说明。 示例界面&#xff1a; 1、类型选择器&#xff1a; QWidget {background-color: rgb(255, 85, 127); }运行结果&#xff08;因为QPushButton是QWidget的子类&#xff0…

MongoDB的备份和恢复命令

一、下载 MongoDB Database Tools 官方网址&#xff1a;Download MongoDB Command Line Database Tools | MongoDB 将解压后的文件夹移动到MongoDB的bin目录下&#xff0c;同时配置mongodb-database-tools的bin目录进入环境变量。 以上有问题请参考文章&#xff1a;使用cmd命…

已解决npm ERR! request to https://registry.npm.taobao.org/@vant%2farea-data failed

在npm insrall的时候&#xff0c;报错&#xff0c;完整报错如下 简单来说就是淘宝原镜像域名&#xff08;http://registry.npm.taobao.org&#xff09;的 HTTPS 证书到期了&#xff0c;导致npm在使用镜像的时候报错&#xff0c;需要更换镜像域名。 清空缓存 npm cache clean …

计算机毕业设计Python+Flask微博情感分析 微博舆情预测 微博爬虫 微博大数据 舆情分析系统 大数据毕业设计 NLP文本分类 机器学习 深度学习 AI

首先安装需要的python库&#xff0c; 安装完之后利用navicat导入数据库文件bili100.sql到mysql中&#xff0c; 再在pycharm编译器中连接mysql数据库&#xff0c;并在设置文件中将密码修改成你的数据库密码。最后运行app.py&#xff0c;打开链接&#xff0c;即可运行。 B站爬虫数…

pytorch学习笔记一:作用、安装和基本使用方法、自动求导机制、自制线性回归模型、常见tensor格式、hub模块介绍

文章目录 一、安装二、基本使用方法①创建一个矩阵②获得随机值③初始化全零矩阵④直接传入数据⑤构建矩阵&#xff0c;然后随机元素值⑥展示矩阵大小⑦矩阵计算8、取索引9、view操作&#xff1a;改变矩阵维度10、与numpy的协同操作 三、自动求导机制1&#xff09;定义tensor成…

介绍一下常用的激活函数?

常用的激活函数 Sigmoid函数Tanh函数ReLU函数Leaky ReLU函数Softmax函数 Sigmoid函数 特点&#xff1a; 将任意实数映射到(0,1)区间内&#xff0c;输出值可以作为概率来解释。 函数平滑且易于求导&#xff0c;但其导数在两端趋近于0&#xff0c;即存在梯度消失问题。 输出值不…

算法训练——day18 两数之和三数之和

1. 两数之和 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案&#xff0c;并且你不能使用两次相同的元素。 你可以按任意顺序返回…

【Java版】云HIS系统源码

云HIS系统介绍 云HIS系统是一款满足基层医疗机构各类业务需要的健康云产品。该产品能帮助基层医疗机构完成日常各类业务&#xff0c;提供病患挂号支持、病患问诊、电子病历、开药发药、会员管理、统计查询、医生站和护士站等一系列常规功能&#xff0c;还能与公卫、PACS等各类…

【有啥问啥】深入解析:机器学习中的过拟合与欠拟合

深入解析&#xff1a;机器学习中的过拟合与欠拟合 在机器学习中&#xff0c;过拟合&#xff08;overfitting&#xff09;和欠拟合&#xff08;underfitting&#xff09;是模型性能中常见的两大挑战。它们反映了模型的学习能力与泛化能力的不平衡&#xff0c;直接影响模型在训练…

mac m1 electron生产环境使用prisma,sqlite

最近在用electron开发一个适合自己的小应用&#xff0c;技术选型中使用prisma和sqlite在进行数据存储&#xff0c;写这篇文章的目的就是用来记录下遇到的一些问题。 开发环境使用prisma 1、开发环境使用prisma非常的简单&#xff0c;只需要按照教程安装prisma&#xff0c;然后…