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.mzph.cn/news/777367.shtml

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

相关文章

FMEA的本质——FMEA软件

免费试用FMEA软件-免费版-SunFMEA FMEA&#xff0c;即故障模式与影响分析&#xff08;Failure Modes and Effects Analysis&#xff09;&#xff0c;是一种预防性的质量工具&#xff0c;广泛应用于各种行业和领域&#xff0c;特别是在制造业、航空航天、医疗设备、汽车工业等领…

AGV全电动无人堆高车选购时要注意的4点

AGV 随着机器人技术在中国的快速发展&#xff0c;国内企业开始推出区别于传统叉车的无人叉车&#xff0c;旨在为企业降本增效&#xff0c;降低人工成本与对人的依赖。同时&#xff0c;也将人工从危险恶劣的环境中解放出来。随着技术的持续提升&#xff0c;如今&#xff0c;无人…

DVB-S系统仿真学习

DVB-S系统用于卫星电视信号传输&#xff0c;发送端框图如下所示 扰码 实际数字通信中&#xff0c;载荷数据的码元会出现长连0或长连1的情况&#xff0c;不利于接收端提取时钟信号&#xff0c;同时会使得数据流中含有大量的低频分量&#xff0c;使得QPSK调制器的相位长时间不变…

【Frida】【Android】05_Objection实战

&#x1f6eb; 系列文章导航 【Frida】【Android】01_手把手教你环境搭建 https://blog.csdn.net/kinghzking/article/details/136986950【Frida】【Android】02_JAVA层HOOK https://blog.csdn.net/kinghzking/article/details/137008446【Frida】【Android】03_RPC https://bl…

线程创建方式、构造方法和线程属性

欢迎各位&#xff01;&#xff01;&#xff01;推荐PC端观看 文章重点&#xff1a;学会五种线程的创造方式 目录 1.开启线程的五种方式 2.线程的构造方法 3.线程的属性及获取方法 1.开启线程的五种方式 创造线程的基本两步&#xff1a;&#xff08;1&#xff09;使用run方法…

2024最新华为OD机试试题库全 -【二叉树计算】- C卷

1. 🌈题目详情 1.1 ⚠️题目 给出一个二叉树如下图所示: 请由该二叉树生成一个新的二叉树,它满足其树中的每个节点将包含原始树中的左子树和右子树的和。 左子树表示该节点左侧叶子节点为根节点的一颗新树;右子树表示该节点右侧叶子节点为根节点的一颗新树。 1.2 �…

智能车主控板原理图原理讲解

智能车主控板原理图原理讲解 综述&#xff1a;本篇文章对智能车主控板的一部分电路进行原理分析&#xff0c;文末附加整体原理图。 1. 电源电路 &#xff08;1&#xff09;通过外接电池供电并通过电源模块电路&#xff0c;运用稳压芯片lm2940&#xff0c;将电源电压转化为5V…

分布式处理

前言 大家好&#xff0c;我是jiantaoyab&#xff0c;这是我作为学习笔记原理篇的最后一章&#xff0c;一台计算机在数据中心里是不够的。因为如果只有一台计算机&#xff0c;我们会遇到三个核心问题。第一个核心问题&#xff0c;叫作垂直扩展和水平扩展的选择问题&#xff0c;…

【leetcode】双“指针”

标题&#xff1a;【leetcode】双指针 水墨不写bug 我认为 讲清楚为什么要用双指针 比讲怎么用双指针更重要&#xff01; &#xff08;一&#xff09;快乐数 编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」 定义为&#xff1a; 对于一个正整数&#xff0c;每一次将该数…

排序C++

题目 法1 sort升序排序&#xff0c;再逆序输出 #include<iostream> #include<algorithm> using namespace std;const int N 5e53;//注意const&#xff0c;全局 int a[N]; int main() {//错误int N5e53;//错误const int a[N];int n;cin >> n;for (int i 1;…

HBase Shell基本操作

一、进入Hbase Shell客户端 先在Linux Shell命令行终端执行start-dfs.sh脚本启动HDFS&#xff0c;再执行start-hbase.sh脚本启动HBase。如果Linux系统已配置HBase环境变量&#xff0c;可直接在任意目录下执行hbase shell脚本命令&#xff0c;就可进入HBase Shell的命令行终端环…

【容器源码篇】Set容器(HashSet,LinkedHashSet,TreeSet的特点)

文章目录 ⭐容器继承关系&#x1f339;Set容器&#x1f5d2;️HashSet源码解析构造方法public HashSet()public HashSet(Collection<? extends E> c)public HashSet(int initialCapacity, float loadFactor)HashSet(int initialCapacity, float loadFactor, boolean dum…

VLAN实验记录---对抗遗忘

sw1的接口6应该调成混杂模式&#xff0c;因为pc2,4,5,6的pvid各不相同而网段相同&#xff0c;所以往上去路由时应该剥离标记&#xff08;VLAN里面是标记而不是标签&#xff09;出去&#xff0c;这样 路由器上的物理接口用来管理不带标记的流量&#xff0c;而vlan2流量的往上打上…

记录 AI绘图 Stable Diffusion的本地安装使用,可搭建画图服务端

开头 最近刷短视频看到了很多关于AI绘图&#xff0c;Midjourney&#xff0c;gittimg.ai&#xff0c;Stable Diffusion等一些绘图AI工具&#xff0c;感受到了AI绘画的魅力。通过chatGPT生成关键词再加上绘图工具&#xff0c;真是完美&#xff0c;文末教大家如何用gpt提词 Midj…

每日算法之接雨水

题目描述 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 示例 1&#xff1a; 输入&#xff1a;height [0,1,0,2,1,0,1,3,2,1,2,1] 输出&#xff1a;6 解释&#xff1a;上面是由数组 [0,1,0,2,1,0,1…

打造核心竞争力:高效Web系统数据中台的设计与实践_光点科技

在数字化的浪潮中&#xff0c;数据已经成为企业赖以生存和发展的核心资源。一个高效的Web系统数据中台&#xff0c;能够赋予企业在激烈的市场竞争中立于不败之地的能力。本文将深入探讨如何设计和实施一个能够提升企业数据管理水平和支持业务决策的高效数据中台架构。 数据中台…

【YOLOv8训练结果评估】YOLOv8如何使用训练好的模型对验证集进行评估及评估参数详解

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

P8623 [蓝桥杯 2015 省 B] 移动距离 Python

[蓝桥杯 2015 省 B] 移动距离 题目描述 X 星球居民小区的楼房全是一样的&#xff0c;并且按矩阵样式排列。其楼房的编号为 $1,2,3, \cdots $ 。 当排满一行时&#xff0c;从下一行相邻的楼往反方向排号。 比如&#xff1a;当小区排号宽度为 6 6 6 时&#xff0c;开始情形如…

腾讯云优惠券领取及使用常见问题解答

随着云计算的普及&#xff0c;腾讯云作为国内领先的云计算服务提供商&#xff0c;为越来越多的企业和个人提供了丰富的云产品和服务。为了帮助用户更好地了解和使用腾讯云优惠券&#xff0c;本文将为大家解答关于腾讯云优惠券领取及使用的常见问题。 一、腾讯云优惠券概述 腾讯…

软件设计师24--概念设计阶段

软件设计师24--概念设计阶段 考点1&#xff1a;概念设计过程考点2&#xff1a;E-R图属性E-R模型-联系类型判断例题&#xff1a;E-R模型-联系类型判断扩充的E-R模型 考点1&#xff1a;概念设计过程 需求分析 --> 抽象数据 --> 设计局部ER模型 --> 合并局部模型消除冲突…