赞
踩
本文详细代码需订阅下面专栏获取(订阅后私信邮箱+项目名):
https://blog.csdn.net/m0_68036862/category_12333038.html
目录
本篇Codelab主要介绍使用DevEco Studio开发工具,高效开发登录应用的案例。使用开发工具以下功能:
使用DevEco Studio开发工具的预览器适配多设备页面。
使用DevEco Studio开发工具运行和调试代码。
使用DevEco Studio开发工具测试代码。
我们首先需要完成HarmonyOS开发环境搭建,可参照如下步骤进行。
本篇Codelab只对核心代码进行讲解,对于完整代码,我们会在源码下载或gitee中提供。
├──entry/src/main
│ ├──cpp // C++代码区
│ │ ├──types // 接口存放目录
│ │ │ └──libentry
│ │ │ ├──index.d.ts // 接口文件
│ │ │ └──oh-package.json5 // 接口注册配置文件
│ │ ├──CMakeLists.txt // CMake打包配置文件
│ │ └──hello.cpp // C++源代码
│ ├──ets // ets代码区
│ │ ├──common
│ │ │ ├──constants
│ │ │ │ ├──CommonConstants.ets // 常量类
│ │ │ │ └──StyleConstants.ets // 格式常量类
│ │ │ ├──data
│ │ │ │ └──SourceData.ets // 数据源
│ │ │ └──utils
│ │ │ ├──CommonUtils.ets // 数据操作工具类
│ │ │ ├──GlobalContext.ets // 全局上下文工具类
│ │ │ ├──Logger.ets // 日志打印工具类
│ │ │ └──MultipleDevicesUtils.ets // 媒体查询工具类
│ │ ├──entryability
│ │ │ └──EntryAbility.ets // 程序入口类
│ │ ├──pages
│ │ │ ├──LoginPage.ets // 登录页面
│ │ │ └──MainPage.ets // 主页面
│ │ ├──view
│ │ │ ├──HomePage.ets // 自定义首页组件
│ │ │ └──MinePage.ets // 自定义我的组件
│ │ └──viewmodel
│ │ ├──ItemData.ets // 数据源类
│ │ └──MainViewModel.ets // 主界面视图Model
│ └──resources // 资源文件目录
└──entry/src/ohosTest
├──ets // 测试代码区
│ ├──test
│ │ ├──Ability.test.ets // Ability单元测试
│ │ ├──List.test.ets // 集成测试类
│ │ └──LoginFunction.test.ets // 登录校验单元测试
│ ├──testability
│ │ ├──pages
│ │ │ └──Index.ets // 测试程序首页
│ │ └──TestAbility.ets // 测试程序入口类
│ └──testrunner
│ └──OpenHarmonyTestRunner.ts // 测试运行类
└──resources // 测试资源文件目录
如何高效开发UI代码,这时需要用到预览器。预览器帮助开发者在开发过程中解决界面快速预览的问题,预览器支持实时预览、动态预览、组件预览和多端设备预览。效果如图所示:
添加或删除UI组件:在开发UI代码过程中,如果添加或删除UI组件,只需按Ctrl+S进行保存,已经打开的预览界面,就会快速刷新预览结果。比如,在登录页面添加Image组件,按Ctrl+S保存,页面刷新后,登录页面的图片就出来了。效果如图所示:
// LoginPage.ets
@Entry
@Component
struct LoginPage {
build() {
Column() {
Image($r('app.media.ic_logo'))
.width($r('app.float.logo_image_size'))
.height($r('app.float.logo_image_size'))
.margin({ bottom: $r('app.float.logo_margin_bottom')
}
...
}
}
修改组件属性:当修改了组件的属性,预览器会实时刷新预览结果,达到快速预览的效果。比如,修改Image图片资源和图片大小,按Ctrl+S保存,预览器会根据最新代码进行预览更新。效果如图所示:
// LoginPage.ets
@Entry
@Component
struct LoginPage {
build() {
Column() {
Image($r('app.media.ic_top'))
.width(100)
.height(100)
.margin({ bottom: $r('app.float.logo_margin_bottom')
}
...
}
}
当UI界面开发完成后,可以在预览器界面对开发完成的页面进行操作,如单击、跳转、滑动等。这些操作和真机设备上界面交互体验一致。比如,登录页面,输入完帐号和密码后,点击登录,完成登录跳转到首页。效果如图所示:
// LoginPage.ets
@Entry
@Component
struct LoginPage {
...
build() {
Column() {
Column() {
TextInput({ placeholder: $r('app.string.account') })
.maxLength(StyleConstants.INPUT_ACCOUNT_LENGTH)
.type(InputType.Number)
.inputStyle()
.onChange((value: string) => {
this.account = value;
})
...
TextInput({ placeholder: $r('app.string.password') })
.maxLength(StyleConstants.INPUT_PASSWORD_LENGTH)
.type(InputType.Password)
.inputStyle()
.onChange((value: string) => {
this.password = value;
})
}
...
Button($r('app.string.login'))
...
.onClick(() => {
CommonUtils.loginArkTS(this.account, this.password);
})
...
}
...
}
}
一个页面可以理解成由若干组件构建而成,比如,HomePage页面从上到下拆分成三个部分,分别是SwiperView、CenterGridView、ListImageView。每个自定义组件头部加上@Preview,在预览时,就可以单独预览自定义组件。效果如图所示:
// HomePage.ets
@Component
export default struct HomePage {
...
build() {
Scroll() {
Column() {
...
// 轮播图组件
SwiperView()
// 网格组件
CenterGridView()
// 图片列表组件
ListImageView()
}
...
}
...
}
}@Preview
@Component
struct SwiperView {
...
build() {
Column() {
Swiper() {
ForEach(mainViewModel.getSwiperImages(), (item: Resource) => {
Image(item)
.borderRadius($r('app.float.swiper_radius'))
}, (item: Resource) => JSON.stringify(item))
}
...
}
}
}@Preview
@Component
struct CenterGridView {
build() {
Column() {
Grid() {
ForEach(mainViewModel.getCenterGridData(), (item: ItemData) => {
GridItem() {
GridItemView({ item: item })
}
}, (item: ItemData) => JSON.stringify(item))
}
...
}
}
}@Preview
@Component
struct ListImageView {
...
build() {
Column() {
Text($r('app.string.home_list'))
.fontSize($r('app.float.normal_text_size'))
.fontWeight(FontWeight.Medium)
.alignSelf(ItemAlign.Start)
.margin({
left: $r('app.float.common_margin'),
top: $r('app.float.common_margin')
})
List({ space: StyleConstants.IMAGE_LIST_SPACE }) {
ForEach(mainViewModel.getListImageData(), (secondItem: ItemData) => {
ListItem() {
ImageItemView({ secondItem: secondItem })
}
.margin({ right: $r('app.float.list_margin') })
.borderRadius($r('app.float.image_list_radius'))
.onClick(() => {
if (!secondItem?.clickPrompt) {
return;
}
CommonUtils.showToastContent(secondItem.clickPrompt);
})
}, (secondItem: ItemData) => JSON.stringify(secondItem.id))
}
...
}
}
}
进行开发多端设备时,因设备的屏幕分辨率、形状、大小等不同,开发者需要在不同的设备上适配应用/服务的UI布局和交互效果。比如,LoginPage页面适配多端设备,这里使用栅格布局进行适配,最终页面效果是在多设备预览下,展示UX对应效果(多设备页面展示效果根据UX设计)。效果如图所示:
在module.json5文件中,添加deviceTypes属性值。例如,我们添加手机设备类型和平板设备类型。
// module.json5
"deviceTypes": [
"phone",
"tablet"
]
在页面布局中使用栅格布局适配多端设备。
// LoginPage.ets
@Entry
@Component
struct LoginPage {
...
build() {
GridRow({
columns: {
// sm设备界面设计总共有4个栅格
sm: StyleConstants.COLUMNS_SM,
// md设备界面设计总共有8个栅格
md: StyleConstants.COLUMNS_MD,
// lg设备界面设计总共有12个栅格
lg: StyleConstants.COLUMNS_LG
},
gutter: {
// 栅格之间水平偏移距离12
x: StyleConstants.GRID_GUTTER
}
}) {
GridCol({
span: {
// 页面占4个栅格
sm: StyleConstants.SPAN_SM,
// 页面占6个栅格
md: StyleConstants.SPAN_MD,
// 页面占8个栅格
lg: StyleConstants.SPAN_LG
}, offset: {
// md设备偏移列数1
md: StyleConstants.OFFSET_MD,
// lg设备偏移列数2
lg: StyleConstants.OFFSET_LG
}
}) {
Column() {
// 登录页头部组件
LoginTitle()
// 登录页底部组件
LoginBottom()
}
}
}
.backgroundColor($r('app.color.background'))
}
}
预览界面添加多个设备尺寸,然后打开多设备预览。效果如图所示:
当我们开发完功能后,想把应用部署到设备上。使用DevEco Studio开发工具运行HarmonyOS应用,查看部署的应用在设备上显示的效果是否与UX设计有偏差。除此之外,开发工具还提供代码调试功能,方便我们快速定位有问题的代码。效果如图所示:
DevEco Studio提供模拟器供开发者运行和调试HarmonyOS应用/服务,单击菜单栏的Tools->Devcie Manager,选择Local Emulator打开本地模拟器。初次使用本地模拟器是需要下载和安装的,模拟器的安装步骤可以查阅官网的指导文档官网的指导文档官网的指导文档自行安装。模拟器下载完成后,就可以启动这个模拟器。效果如图所示:
模拟器启动完成后,单击IDE右上角的运行图标,就可以把应用部署到本地模拟器。效果如图所示:
这样,就成功把应用部署到本地模拟器了。效果如图所示:
如果你有HarmonyOS设备,可以把当前应用部署到本地真机。连上本地真机设备后,进入File > Project Structure > Project > Signing Configs界面,勾选”Support HarmonyOS”和“Automatically generate signature”。即可完成签名,如果未登录,请先单击Sign In进行登录,然后完成签名。效果如图所示:
签名完成后,DevEco Studio开发工具会把对应的签名文件关联上。效果如图所示:
DevEco Studio提供了丰富的HarmonyOS应用/服务调试能力,在工具栏中,选择调试的设备,并单击Debug启动调试。效果如图所示:
比如,我们需要调试loginCheckArkTS这个方法,在if、else if和else三个判断语句设置断点,启动调试。当只输入帐号或者只输入密码时,点击登录,此时断点会进入if或者else if语句,提示用户输入帐号或者密码。效果如图所示:
测试代码需要在ohosTest->ets->test目录下新建一个LoginFunctionTest测试类,在测试类里面添加需要验证的代码。点击左边运行可查看验证结果。效果如图所示:
单元测试是函数级别的验证。函数是产品开发实现的最基本单元,单元测试通过验证产品代码的函数输入输出,确保每个函数都稳定可靠。比如,当前案例中有一个登录检查方法loginCheck,判断帐号和密码是否输入。
// ohosTest/ets/testability/pages/Index.ets
export function loginCheck(account: string, password: string): boolean {
if (account === '' || password === '') {
return true;
} else {
return false;
}
}
这里设置3条测试用例,其中emptyPasswordTest(只输入帐号,不输入密码,期望为true)和notEmptyTest(输入帐号和密码,期望为false)验证通过。emptyAccountTest(只输入密码,不输入帐号,期望为false),验证不通过(测试结果和期望不符合)。效果如图所示:
集成测试是把若干个单元组装到一起进行测试,属于交付的功能特性测试,是模块和特性维度的测试。比如上面的例子,已经完成了loginCheck登录方法的校验。现在期望系统能自动输入帐号“123”,密码“123456”,输入完成后能自动的帮我们点击登录按钮完成登录页面的校验,这个时候我们可以使用UITest来模拟UI的相关操作。效果如图所示:
要完成登录页面的测试,我们要进行如下操作:
由此,我们实现了自动输入帐号、密码并点击登录的功能。
// LoginFunction.test.ets
describe('verifyLoginTest', () => {
it('loginTest', 0, async () => {
await startAbility('com.huawei.logindemo', 'EntryAbility');
let driver = Driver.create();
await driver.delayMs(waitUiReadyMs);
let input = await driver.findComponents(ON.type('TextInput'));
// 输入帐号123
await input[0].inputText('123');
await driver.delayMs(waitUiReadyMs);
// 输入密码123456
await input[1].inputText('123456');
await driver.delayMs(waitUiReadyMs);
// 隐藏键盘
inputMethod.getController().stopInput();
let btn = await driver.findComponent(ON.id('loginButtonId'));
await btn.click();
await driver.delayMs(waitUiReadyMs);
});
});
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。