赞
踩
本篇Codelab基于Stage模型实现带有卡片的计步应用,用于介绍卡片的开发及生命周期实现。需要完成以下功能:
完成本篇Codelab我们首先要完成开发环境的搭建,本示例以RK3568开发板为例,参照以下步骤进行:
2.搭建烧录环境。
3.搭建开发环境。
本篇Codelab只对核心代码进行讲解。
- ├──entry/src/main/ets // 代码区
- │ ├──common
- │ │ ├──constants
- │ │ │ └──CommonConstants.ets // 常量类
- │ │ ├──database
- │ │ │ ├──Form.ets // 数据库卡片操作
- │ │ │ └──SensorData.ets // 数据库行走步数操作
- │ │ └──utils
- │ │ ├──ChartDataUtils.ets // 图表数据操作工具类
- │ │ ├──DatabaseUtils.ets // 数据库工具类
- │ │ ├──DateUtils.ets // 日期工具类
- │ │ ├──GlobalContext.ets // 项目工具类
- │ │ └──Logger.ets // 日志打印工具类
- │ ├──entryability
- │ │ └──EntryAbility.ets // 程序入口类
- │ ├──entryformability
- │ │ └──EntryFormAbility.ets // 卡片创建,更新,删除操作类
- │ ├──pages
- │ │ └──MainPage.ets // 主界面
- │ └──viewmodel
- │ ├──ChartPoint.ets // 图表点类
- │ ├──ChartValues.ets // 图表值类
- │ ├──FormData.ets // 表单数据类
- │ └──PointStyle.ets // 图表点样式类
- ├──entry/src/main/js // js代码区
- │ ├──card2x2 // 2x2卡片目录
- │ ├──card2x4 // 2x4卡片目录
- │ ├──common // 卡片资源目录
- │ └──i18n // 卡片国际化目录
- └──entry/src/main/resources // 资源文件目录
元服务卡片需要用数据库保存不同时间、不同卡片的数据,而且在添加多张卡片情况下,需要保持数据同步刷新。因此需要创建两张表,一张是保存卡片信息,另一张是记录当天行走步数。
1.数据库创建使用的SQLite。
- // CommonConstants.ets
- // 表单SQLite
- static readonly CREATE_TABLE_FORM: string = 'CREATE TABLE IF NOT EXISTS Form ' +
- '(id INTEGER PRIMARY KEY AUTOINCREMENT, formId TEXT NOT NULL, formName TEXT NOT NULL, dimension INTEGER)';
- // 行走步数SQLite
- static readonly CREATE_TABLE_SENSOR_DATA: string = 'CREATE TABLE IF NOT EXISTS SensorData ' +
- '(id INTEGER PRIMARY KEY AUTOINCREMENT, date TEXT NOT NULL, stepsValue INTEGER)';
2.在EntryAbility的onCreate方法通过DatabaseUtils.createRdbStore方法创建数据库,并创建相应的表。
- // EntryAbility.ets
- onCreate(want: Want, param: AbilityConstant.LaunchParam): void {
- GlobalContext.getContext().setObject('abilityWant', want);
- GlobalContext.getContext().setObject('abilityParam', param);
- DatabaseUtils.createRdbStore(this.context).then((rdbStore: Object | undefined) => {
- // 添加前三天行走模拟数据
- DatabaseUtils.addSimulationData(rdbStore as DataRdb.RdbStore);
- }).catch((error: Error) => {
- ...
- });
- }
需要在MainPage的aboutToAppear调用requestNotification方法申请通知栏权限,效果如图所示:
- // MainPage.ets
- aboutToAppear() {
- // 申请通知栏权限
- this.requestNotification();
- ...
- }
-
- requestNotification() {
- Notification.requestEnableNotification().then(() => {
- ...
- }).catch((err: Error) => {
- ...
- });
- }
通过aboutToAppear的setInterval方法开启定时器,当定时器到10秒后,通过DatabaseUtils.sendNotifications方法发送消息到通知栏。效果如图所示:
- // DatabaseUtils.ets
- // 发送通知
- sendNotifications(stepsValue: string, notificationId: number) {
- // 获取当前系统语言
- let notificationBarTitle: string;
- let Language: string = I18n.System.getSystemLanguage();
- // 判断是否为中文
- if (Language.match(CommonConstants.CHINESE_LANGUAGE)) {
- notificationBarTitle = CommonConstants.NOTIFICATIONS_TITLE_GONE_TODAY_ZH +
- stepsValue + CommonConstants.NOTIFICATIONS_TITLE_STEPS_ZH;
- } else {
- notificationBarTitle = CommonConstants.NOTIFICATIONS_TITLE_GONE_TODAY_EN +
- stepsValue + CommonConstants.NOTIFICATIONS_TITLE_STEPS_EN;
- }
- // 发布NotificationRequest.
- Notification.publish({
- id: CommonConstants.NOTIFICATIONS_ID,
- content: {
- contentType: Notification.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
- normal: {
- title: notificationBarTitle,
- text: ''
- }
- }
- }).then(() => {
- ...
- });
- }
使用元服务卡片分为四步:创建、初始化、更新、删除。
2.然后选择第一个选项下面带有Hello World字样,点击下一步Next。
3.填写卡片名字(Service widget name)、卡片介绍(Description)、是否开启低代码开发(Enable Super Visual)、开发语言(ArkTS和JS)、支持卡片规格(Support dimension)、关联表单(Ability name)点击Finish完成创建。如需创建多个卡片目录重新按照步骤1执行。
4.创建完卡片后,同级目录出现js目录,然后开发者在js目录下使用hml+css+json开发js卡片页面。
应用选择添加元服务卡片到桌面后,在EntryFormAbility的onAddForm方法进行卡片初始化操作,效果如图所示:
- // EntryFormAbility.ets
- onAddForm(want: Want) {
- let formId: string = want.parameters !== undefined ?
- want.parameters[CommonConstants.FORM_PARAM_IDENTITY_KEY] as string : '';
- let formName: string = want.parameters !== undefined ?
- want.parameters[CommonConstants.FORM_PARAM_NAME_KEY] as string : '';
- let dimensionFlag: number = want.parameters !== undefined ?
- want.parameters[CommonConstants.FORM_PARAM_DIMENSION_KEY] as number : 0;
- // 创建数据库
- DatabaseUtils.createRdbStore(this.context).then((rdbStore: Object | undefined) => {
- // 存储卡片信息
- let form: Form = new Form();
- form.formId = formId;
- form.formName = formName;
- form.dimension = dimensionFlag;
- ...
- DatabaseUtils.insertForm(form, rdbStore as DataRdb.RdbStore);
- getToDaySteps(rdbStore as DataRdb.RdbStore, dimensionFlag, formId);
- }).catch((error: Error) => {
- ...
- });
- ...
- // 初始化卡片数据
- let formData: FormData = new FormData();
- formData.percent = 0;
- formData.steps = 0;
- return FormBindingData.createFormBindingData(formData);
- };
1.初始化加载主页面布局之前,在MainPage的aboutToAppear方法中,调用setInterval方法开启定时器。时间到则先通过DatabaseUtils.insertValues方法把步数插入到数据库,再通过DatabaseUtils.updateForms方法更新卡片步数。
- // MainPage.ets
- aboutToAppear() {
- ...
- DatabaseUtils.getSensorData(rdbStoreValue, DateUtils.getDate(0))
- .then((sensorData: SensorData) => {
- if (sensorData) {
- this.stepsValue = sensorData.stepsValue;
- }
- // 开启定时器
- this.intervalId = setInterval(() => {
- ...
- DatabaseUtils.insertValues(this.stepsValue, rdbStoreValue);
- DatabaseUtils.updateForms(this.stepsValue, rdbStoreValue);
- }, CommonConstants.INTERVAL_DELAY_TIME);
- ...
- });
- }
-
- // DatabaseUtils.ets
- updateForms(stepValue: number, rdbStore: DataRdb.RdbStore) {
- let predicates: DataRdb.RdbPredicates =
- new DataRdb.RdbPredicates(CommonConstants.TABLE_FORM);
- // 查询卡片
- rdbStore.query(predicates).then((resultSet: DataRdb.ResultSet) => {
- ...
- // 查询第一行
- resultSet.goToFirstRow();
- do {
- let formId: string = resultSet.getString(resultSet.getColumnIndex(CommonConstants.FIELD_FORM_ID));
- let dimension: number = resultSet.getLong(resultSet.getColumnIndex(CommonConstants.FIELD_DIMENSION));
- ChartDataUtils.getFormData(formId, stepValue, dimension, rdbStore)
- .then((formData: FormData) => {
- // 更新多张卡片
- FormProvider.updateForm(formData.formId, FormBindingData.createFormBindingData(formData))
- .catch((error: Error) => {
- ...
- });
- }).catch((error: Error) => {
- ...
- });
- } while (resultSet.goToNextRow());
- resultSet.close();
- }).catch((error: Error) => {
- ...
- });
- }
2.卡片添加到桌面后,在EntryFormAbility的onAddForm方法中,调用formProvider.setFormNextRefreshTime方法设置倒计时。时间到了则通过updateSensorData方法更新卡片步数。
- // EntryFormAbility.ets
- onAddForm(want: Want) {
- ...
- // 五分钟倒计时
- formProvider.setFormNextRefreshTime(formId, CommonConstants.FIVE_MINUTES, (error, data) => {
- ...
- });
- }
-
- onUpdateForm(formId: string) {
- // 更新步数
- this.updateSensorData();
- ...
- }
-
- updateSensorData() {
- DatabaseUtils.createRdbStore(this.context).then((rdbStore: Object | undefined) => {
- ...
- // 获取今天步数
- let getSensorData: Promise<SensorData> =
- DatabaseUtils.getSensorData(rdbStore as DataRdb.RdbStore, DateUtils.getDate(0));
- getSensorData.then((sensorData: SensorData) => {
- let stepValue: number = 0;
- if (sensorData) {
- stepValue = sensorData.stepsValue;
- }
- // 更新卡片数据
- DatabaseUtils.updateForms(stepValue, rdbStore);
- }).catch((error: Error) => {
- ...
- });
- }).catch((error: Error) => {
- ...
- });
- }
3.通过src/main/resources/base/profile/form_config.json配置文件,根据updateDuration或者scheduledUpdateTime字段配置刷新时间。updateDuration优先级高于scheduledUpdateTime,两者同时配置时,以updateDuration配置的刷新时间为准。当配置的刷新时间到了,系统调用onUpdateForm方法进行更新。
- // form_config.json
- {
- // 卡片的类名
- "name": "card2x2",
- // 卡片的描述
- "description": "This is a service widget.",
- // 卡片对应完整路径
- "src": "./js/card2x2/pages/index/index",
- // 定义与显示窗口相关的配置
- "window": {
- "designWidth": 720,
- "autoDesignWidth": true
- },
- // 卡片的主题样式
- "colorMode": "auto",
- // 是否为默认卡片
- "isDefault": true,
- // 卡片是否支持周期性刷新
- "updateEnabled": true,
- // 采用24小时制,精确到分钟
- "scheduledUpdateTime": "00:00",
- // 当取值为0时,表示该参数不生效,当取值为正整数N时,表示刷新周期为30*N分钟。
- "updateDuration": 1,
- // 卡片默认外观规格
- "defaultDimension": "2*2",
- // 卡片支持外观规格
- "supportDimensions": [
- "2*2"
- ]
- }
-
- // EntryFormAbility.ets
- onUpdateForm(formId: string) {
- // 更新步数
- updateSensorData();
- ...
- }
当用户需要删除元服务卡片时,可以在EntryFormAbility的onRemoveForm方法中,通过DatabaseUtils.deleteFormData方法删除数据库中对应的卡片信息。
- // EntryFormAbility.ets
- onRemoveForm(formId: string) {
- DatabaseUtils.createRdbStore(this.context).then((rdbStore: Object | undefined) => {
- ...
- // 删除数据库中对应的卡片信息
- DatabaseUtils.deleteFormData(formId, rdbStore as DataRdb.RdbStore);
- }).catch((error: Error) => {
- ...
- });
- }
-
- // DatabaseUtils.ets
- deleteFormData(formId: string, rdbStore: DataRdb.RdbStore) {
- let predicates: DataRdb.RdbPredicates = new DataRdb.RdbPredicates(CommonConstants.TABLE_FORM);
- predicates.equalTo(CommonConstants.FIELD_FORM_ID, formId);
- rdbStore.delete(predicates).catch((error: Error) => {
- ...
- });
- }
您已经完成了本次Codelab的学习,并了解到以下知识点:
为了帮助大家更深入有效的学习到鸿蒙开发知识点,小编特意给大家准备了一份全套最新版的HarmonyOS NEXT学习资源,获取完整版方式请点击→《HarmonyOS教学视频》
获取完整版白皮书方式请点击→《鸿蒙生态应用开发白皮书V2.0PDF》
一、入门必看
二、HarmonyOS 概念
三、如何快速入门?《鸿蒙基础入门学习指南》
四、开发基础知识
五、基于ArkTS 开发
更多了解更多鸿蒙开发的相关知识可以参考:《鸿蒙 (Harmony OS)开发学习手册》
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。