HarmonyOS实战开发-实现带有卡片的电影应用

介绍

本篇Codelab基于元服务卡片的能力,实现带有卡片的电影应用,介绍卡片的开发过程和生命周期实现。需要完成以下功能:

  1. 元服务卡片,用于在桌面上添加2x2或2x4规格元服务卡片。
  2. 关系型数据库,用于创建、查询、添加、删除卡片数据。

相关概念

  • 关系型数据库:关系型数据库基于SQLite组件提供了一套完整的对本地数据库进行管理的机制,对外提供了一系列的增、删、改、查等接口,也可以直接运行用户输入的SQL语句来满足复杂的场景需要。
  • 元服务卡片:卡片是一种界面展示形式,可以将应用的重要信息或操作前置到卡片,以达到服务直达、减少体验层级的目的。卡片提供方:显示卡片内容,控制卡片布局以及控件点击事件。卡片使用方:显示卡片内容的宿主应用,控制卡片在宿主中展示的位置。卡片管理服务:用于管理系统中所添加卡片的常驻代理服务,包括卡片对象的管理与使用,以及卡片周期性刷新等。

环境搭建

软件要求

  • DevEco Studio版本:DevEco Studio 3.1 Release。
  • OpenHarmony SDK版本:API version 9。

硬件要求

  • 开发板类型:润和RK3568开发板。
  • OpenHarmony系统:3.2 Release。

环境搭建

  1. 获取OpenHarmony系统版本:标准系统解决方案(二进制)。以3.2 Release版本为例:

2.搭建烧录环境。

  1. 完成DevEco Device Tool的安装
  2. 完成RK3568开发板的烧录

3.搭建开发环境。

  1. 开始前请参考工具准备,完成DevEco Studio的安装和开发环境配置。
  2. 开发环境配置完成后,请参考使用工程向导创建工程(模板选择“Empty Ability”)。
  3. 工程创建完成后,选择使用真机进行调测。

代码结构解读

本篇Codelab只对核心代码进行讲解。

├──entry/src/main/ets            // 代码区     
│  ├──common  
│  │  ├──constants
│  │  │  ├──CommonConstants.ets  // 常量类
│  │  │  └──StyleConstants.ets   // 格式常量类
│  │  ├──datasource
│  │  │  ├──DataSource.ets       // 懒加载数据源
│  │  │  └──MovieListData.ets    // 电影列表数据 
│  │  └──utils
│  │     ├──CommonUtils.ets      // 数据操作工具类  
│  │     ├──GlobalContext.ets    // 全局上下文工具类
│  │     └──Logger.ets           // 日志打印工具类
│  ├──detailsability
│  │  └──EntryDetailsAbility.ets // 电影详情入口类
│  ├──entryability
│  │  └──EntryAbility.ets        // 程序入口类
│  ├──entryformability
│  │  └──EntryFormAbility.ets    // 卡片创建,更新,删除操作类
│  ├──pages
│  │  ├──MovieDetailsPage.ets    // 电影详情页
│  │  └──MovieListPage.ets       // 主页面
│  ├──view
│  │  ├──MovieDetailsTitle.ets   // 电影详情头部组件
│  │  ├──MovieItem.ets           // 列表item组件
│  │  ├──MovieStarring.ets       // 电影主演组件
│  │  ├──MovieStills.ets         // 电影剧照组件
│  │  ├──StarsWidget.ets         // 电影评分组件
│  │  └──StoryIntroduce.ets      // 电影简介组件
│  └──viewmodel
│     ├──FormBean.ets            // 卡片对象
│     ├──FormDataBean.ets        // 卡片数据对象
│     └──MovieDataBean.ets       // 电影数据对象
├──entry/src/main/js             // js代码区
│  ├──card2x2                    // 2x2卡片目录
│  ├──card2x4                    // 2x4卡片目录
│  └──common                     // 卡片资源目录
└──entry/src/main/resources      // 资源文件目录

关系型数据库

元服务卡片需要用数据库保存不同卡片数据,而且在添加多张卡片情况下,需要保持数据同步刷新。因此需要创建一张表,用于保存卡片信息。

  1. 数据库创建使用的SQLite。
// CommonConstants.ets
// 创建数据库表结构
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)';

2.在EntryAbility的onCreate方法通过CommonUtils.createRdbStore方法创建数据库,并创建相应的表。

// EntryAbility.ets
export default class EntryAbility extends UIAbility {onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {...// 创建数据库CommonUtil.createRdbStore(this.context);}
}// CommonUtils.ets
import relationalStore from '@ohos.data.relationalStore';async createRdbStore(context: Context) {let rdbStore = GlobalContext.getContext().getObject('rdbStore') as relationalStore.RdbStore;if (this.isEmpty(rdbStore)) {rdbStore = await relationalStore.getRdbStore(context, CommonConstants.STORE_CONFIG);if (!this.isEmpty(rdbStore)) {rdbStore.executeSql(CommonConstants.CREATE_TABLE_FORM).catch((error: Error) => {Logger.error(CommonConstants.TAG_COMMON_UTILS, 'executeSql error ' + JSON.stringify(error));});GlobalContext.getContext().setObject('rdbStore', rdbStore);}}return rdbStore;
}

构建应用页面

电影卡片应用有两个页面,分别是电影列表和电影详情。

电影列表

电影列表采用Column容器嵌套List和自定义组件MovieItem形式完成页面整体布局,效果如图所示:

// MovieListPage.ets
build() {Column() {...List({ space: StyleConstants.LIST_COMPONENT_SPACE }) {LazyForEach(this.dataSource, (item: MovieDataBean) => {ListItem() {// 电影itemMovieItem({ movieItem: item });}}, (item: MovieDataBean) => JSON.stringify(item))}...}...
}// MovieItem.ets
aboutToAppear() {if (CommonUtils.isEmpty(this.movieItem)) {Logger.error(CommonConstants.TAG_MOVIE_ITEM, 'movieItem is null');return;}// 获取电影索引this.sort = this.movieItem.sort;...
}build() {Row(){...Text($r('app.string.want_to_see'))....onClick(() => {router.pushUrl({url: CommonConstants.SEE_BUTTON_PUSH,params: {index: this.sort}}).catch((error: Error) => {...});})}...
}

电影详情

电影详情采用Column容器嵌套自定义组件MovieDetailsTitle、StoryIntroduce、MovieStarring和MovieStills形式完成页面整体布局,效果如图所示:

// MovieDetailPage.ets
aboutToAppear() {let index: number = 0;let params = router.getParams() as Record<string, Object>;if (!CommonUtils.isEmpty(params)) {index = params.index as number;} else {let position = GlobalContext.getContext().getObject('position') as number;index = position ?? 0;}let listData: MovieDataBean[] = CommonUtils.getListData();if (CommonUtils.isEmptyArr(listData)) {Logger.error(CommonConstants.TAG_DETAILS_PAGE, 'listData is 0');return;}this.movieData = listData[index];this.introduction = listData[index].introduction;
}build() {Column() {...Column() {// 电影详情头部组件MovieDetailsTitle({movieDetail: this.movieData})// 剧情简介组件StoryIntroduce({introduction: this.introduction})}...// 电影主演组件MovieStarring()// 电影剧照组件MovieStills()}...
}

元服务卡片

使用元服务卡片分为四步:创建、初始化、更新、删除。

创建元服务卡片目录

  1. 在main目录下,点击鼠标右键 > New > Service Widget。

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) {if (want.parameters === undefined) {return formBindingData.createFormBindingData();}let formId: string = want.parameters[CommonConstants.IDENTITY_KEY] as string;let formName: string = want.parameters[CommonConstants.NAME_KEY] as string;let dimensionFlag: number = want.parameters[CommonConstants.DIMENSION_KEY] as number;CommonUtils.createRdbStore(this.context).then((rdbStore: relationalStore.RdbStore) => {let form: FormBean = new FormBean();form.formId = formId;form.formName = formName;form.dimension = dimensionFlag;CommonUtils.insertForm(form, rdbStore);}).catch((error: Error) => {Logger.error(CommonConstants.TAG_FORM_ABILITY, 'onAddForm create rdb error ' + JSON.stringify(error));});let listData: MovieDataBean[] = CommonUtils.getListData();let formData = CommonUtils.getFormData(listData);return formBindingData.createFormBindingData(formData);
}

更新元服务卡片

  1. 初始化加载电影列表布局之前,在MovieListPage的aboutToAppear方法中,通过CommonUtils.startTimer方法开启定时器,时间到则调用updateMovieCardData方法更新电影卡片数据。
// MovieListPage.ets
aboutToAppear() {...// 启动定时器,每5分钟更新一次电影卡片数据。CommonUtils.startTimer();
}// CommonUtils.ets
startTimer() {let intervalId = GlobalContext.getContext().getObject('intervalId') as number;if (this.isEmpty(intervalId)) {intervalId = setInterval(() => {let rdbStore = GlobalContext.getContext().getObject('rdbStore') as relationalStore.RdbStore;this.updateMovieCardData(rdbStore);}, CommonConstants.INTERVAL_DELAY_TIME);}GlobalContext.getContext().setObject('intervalId', intervalId);
}// 更新电影卡片数据
updateMovieCardData(rdbStore: relationalStore.RdbStore) {if (this.isEmpty(rdbStore)) {Logger.error(CommonConstants.TAG_COMMON_UTILS, 'rdbStore is null');return;}let predicates: relationalStore.RdbPredicates = new relationalStore.RdbPredicates(CommonConstants.TABLE_NAME);rdbStore.query(predicates).then((resultSet: relationalStore.ResultSet) => {if (resultSet.rowCount <= 0) {Logger.error(CommonConstants.TAG_COMMON_UTILS, 'updateCardMovieData rowCount <= 0');return;}let listData: MovieDataBean[] = this.getListData();resultSet.goToFirstRow();do {let formData = this.getFormData(listData);let formId: string = resultSet.getString(resultSet.getColumnIndex(CommonConstants.FORM_ID));formProvider.updateForm(formId, formBindingData.createFormBindingData(formData)).catch((error: Error) => {Logger.error(CommonConstants.TAG_COMMON_UTILS, 'updateForm error ' + JSON.stringify(error));});} while (resultSet.goToNextRow());resultSet.close();}).catch((error: Error) => {Logger.error(CommonConstants.TAG_COMMON_UTILS, 'updateCardMovieData error ' + JSON.stringify(error));});

2.通过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) {CommonUtils.createRdbStore(this.context).then((rdbStore: relationalStore.RdbStore) => {CommonUtils.updateMovieCardData(rdbStore);}).catch((error: Error) => {...});...
}

删除元服务卡片

当用户需要删除元服务卡片时,可以在EntryFormAbility的onRemoveForm方法中,通过CommonUtils.deleteFormData方法删除数据库中对应的卡片信息。

// EntryFormAbility.ets
onRemoveForm(formId: string) {CommonUtils.createRdbStore(this.context).then((rdbStore: relationalStore.RdbStore) => {// 从数据库中删除电影卡片信息CommonUtils.deleteFormData(formId, rdbStore);}).catch((error: Error) => {...});
}// CommonUtils.ets
deleteFormData(formId: string, rdbStore: relationalStore.RdbStore) {...let predicates: relationalStore.RdbPredicates = new relationalStore.RdbPredicates(CommonConstants.TABLE_NAME);predicates.equalTo(CommonConstants.FORM_ID, formId);rdbStore.delete(predicates).catch((error: Error) => {...});
}

总结

您已经完成了本次Codelab的学习,并了解到以下知识点:

  1. 使用关系型数据库插入、更新、删除卡片数据。
  2. 使用FormExtensionAbility创建、更新、删除元服务卡片。

为了帮助大家更深入有效的学习到鸿蒙开发知识点,小编特意给大家准备了一份全套最新版的HarmonyOS NEXT学习资源,获取完整版方式请点击→《HarmonyOS教学视频

HarmonyOS教学视频:语法ArkTS、TypeScript、ArkUI等.....视频教程

鸿蒙生态应用开发白皮书V2.0PDF:

获取完整版白皮书方式请点击→《鸿蒙生态应用开发白皮书V2.0PDF

鸿蒙 (Harmony OS)开发学习手册

一、入门必看

  1. 应用开发导读(ArkTS)
  2. ……

二、HarmonyOS 概念

  1. 系统定义
  2. 技术架构
  3. 技术特性
  4. 系统安全
  5. ........

三、如何快速入门?《做鸿蒙应用开发到底学习些啥?》

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. ……

四、开发基础知识

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. ……

五、基于ArkTS 开发

  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. ……

更多了解更多鸿蒙开发的相关知识可以参考:《鸿蒙 (Harmony OS)开发学习手册

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

主从复制与读写分离

前言&#xff1a; 在企业应用中&#xff0c;成熟的业务通常数据量都比较大&#xff0c;单台MySQL在安全性、高可用性和高并发方面 都无法满足实际的需求&#xff1f; 配置多台主从数据库服务器以实现读写分离 一 主从复制的工作原理 ①Master节点将数据的改变记录成二进制…

使用Zabbix监控NAS目录状态

在企业的数据存储和共享中,网络附加存储(NAS)扮演着至关重要的角色。为了确保NAS设备的稳定运行和数据的完整性,对其进行实时监控是必不可少的。Zabbix作为一款开源的网络监控解决方案,能够帮助我们实现这一目标。本文将介绍如何使用Zabbix监控NAS目录状态,以确保及时发现…

Java_20 元素和最小的山形三元组

元素和最小的山形三元组 给你一个下标从 0 开始的整数数组 nums 。 如果下标三元组 (i, j, k) 满足下述全部条件&#xff0c;则认为它是一个 山形三元组 &#xff1a; i < j < knums[i] < nums[j] 且 nums[k] < nums[j] 请你找出 nums 中 元素和最小 的山形三元…

使用mybatis的@Interceptor实现拦截sql

一 mybatis的拦截器 1.1 拦截器介绍 拦截器是一种基于 AOP&#xff08;面向切面编程&#xff09;的技术&#xff0c;它可以在目标对象的方法执行前后插入自定义的逻辑。 1.2 语法介绍 1.注解Intercepts Intercepts({Signature(type StatementHandler.class, method “…

vue-devtools 不显示的问题

vue 项目中浏览器右上角可以显示出插件&#xff0c;但是控制台却没有显示。 项目中在main.js中添加设置devtools为trueVue.config.devtools true插件显示可以使使用&#xff0c;控制台没有显示VUE选项 项目使用了 externals 打包优化&#xff0c;使用了vue的压缩版本&#x…

Verilog语法之case语句学习

case分支语句是一种实现多路分支控制的分支语句。与使用if-else条件分支语句相比&#xff0c;采用case分支语句来实现多路控制会变得更加的方便直观。 case分支语句通常用于对微处理器指令译码功能的描述以及对有限状态机的描述。Case分支语句有“case”、“casez”、“casex”…

Django创建多app应用

目录 1. 引言 2. 多app创建的两种方式 2.1 多个app结构 2.2 单个apps多个app 3. 最后 1. 引言 在平常业务开发中&#xff0c;我们遇到的功能可能会有很多&#xff0c;单个app的应用可能无法满足我们 这个时候&#xff0c;我们就需要多app应用&#xff0c;例如&#xff1a…

[RAM] 图解 RAM 结构原理

主页&#xff1a; 元存储博客 文章目录 前言1. Channel2. Dimm3. Rank4. Bank5. Row6. Column7. Beat8. Burst Length总结 前言 从CPU至DRAM晶粒之间依据层级由大至小为channel>DIMM>rank>chip>bank>row/column。 图片来源&#xff1a; 电脑王 DRAM层级关系 DR…

区块链dapp开发 dapp系统开发方案

在区块链技术的兴起和普及的推动下&#xff0c;去中心化应用程序&#xff08;DApp&#xff09;成为了当前数字世界中的热门话题之一。DApp 的开发不仅需要考虑技术方面的挑战&#xff0c;还需要深入了解区块链的工作原理和应用场景。本文将介绍一种 DApp 系统开发的基本方案&am…

SpringBoot登录校验(三)

​​​​​​​SpringBoot 登录认证&#xff08;一&#xff09;-CSDN博客 SpringBoot 登录认证&#xff08;二&#xff09;-CSDN博客 SpringBoot登录校验&#xff08;三&#xff09;-CSDN博客 前面我们介绍了传统的会话跟踪技术cookie和sesstion&#xff0c;本节讲解令牌技术…

Python数据分析必备工具——Pandas模块及其应用

Python数据分析必备工具——Pandas模块及其应用 外部数据的读取文本文件的读取语法示例 电子表格的读取语法示例 数据库数据的读取与操作语法 数据操作数据概述语法 数据筛选语法 数据清洗数据类型语法示例 沉余数据语法示例 异常值的识别与处理缺失值的识别与处理语法示例 数据…

Docker命令及部署Java项目

文章目录 简介Docker镜像镜像列表查找镜像拉取镜像删除镜像镜像标签 Docker容器容器启动容器查看容器停止和重启后台模式和进入强制停止容器清理停止的容器容器错误日志容器别名及操作 Docker部署Java项目 简介 Docker是一种容器化技术&#xff0c;可以帮助开发者轻松打包应用…