HarmonyOS JS卡片之“彩票开奖查询”及避坑指北 原创 精华
前言
接触鸿蒙开发已经有3个来月了,最近开始在看鸿蒙卡片开发。因为之前的开发大都是基于Java UI,但按官方的说法,JS卡片相比Java卡片有更大的优势,故决定写个JS卡片的demo来练练手。碰巧,前几天和媳妇儿在散步时捡到1元钱,没能交给警察叔叔,媳妇儿就提议“我们把它昧了吧,买张彩票。”由于不是老CM,没有关注开奖的习惯,想着要是能把开奖结果放在手机桌面显示就好了,这样就不会错过我一夜暴富的机会了。有了需求就开撸,然后就有了这篇文章!
项目简介
-
本项目基于API 6开发,demo运行在API 6以下的手机上会出现部分功能不能使用的现象。
-
卡片功能上实现了双色球、大乐透、福彩3D的最近一期开奖结果查询,点击卡片“刷新”按钮,调用接口更新最新数据;点击“查看更多”按钮,跳转至应用主界面。
-
应用主界面上实现了双色球、大乐透、福彩3D近50期开奖结果查看
-
以上数据均使用了 聚合数据的
https://www.juhe.cn/docs/api/id/300
免费接口(需申请key,一个key一天可免费调用100次,如遇key使用次数过多导致接口请求失败情况时,开发者可自行申请key并替换Constants.java
文件下的JH_KEY
常量值),数据可能会有延迟 -
卡片开发部分使用了卡片的JS UI框架,但由于系统PA与FA相互调用的限制问题,卡片的业务逻辑部分仍然采用Java代码编写(PS:最开始的想法是尽量可能的少依赖Java代码,故尝试了JS FA与Java PA相互调用的方式,但当应用进程被干掉时,Java端无法再调用到JS端方法。这样就导致JS只能写UI部分,业务逻辑还得Java层实现。有知道解决办法的也麻烦告知一声)
-
卡片业务层使用Java开发,采用了简单的MVP架构,网络请求和数据处理部分使用了rxjava3+retrofit框架
-
应用主界面使用了JS-UI框架实现
实现效果
请忽略我粗陋的UI设计和GIF的渣渣像素。
卡片效果 | 详情效果 |
---|---|
![]() |
![]() |
项目代码结构分析
-
base
IBasePresenter:MVP架构中presenter基类接口
IBaseView:MVP架构中view基类接口
-
network
-
bean
LotteryBean:彩票详情接口返回对应model
-
CachedLotteryDetailUtil :彩票详情接口请求工具类,主要作用是防止重复调用详情接口
-
LogInterceptor:OKhttp日志拦截工具类
-
LotteryAPI:接口请求类,通过retrofit注解,将接口返回数据转化为实体类
-
Services:配置Retrofit并提供
-
-
presenter
- IMainContract:MVP中 view与presenter的桥梁
- MainPresenter:提供彩票详情接口的请求,并处理接口返回数据为卡片需要的ZSONObject对象
-
utils
LogUtil:日志打印工具类
-
widget
- controller
- FormController:创建卡片时自动生成,卡片管理器的抽象基类
- FormControllerManager:创建卡片时自动生成,管理各个FormController 的工具类
- dltwidget.DltWidgetImpl :大乐透卡片管理类,提供了创建卡片、更新卡片、删除卡片、卡片点击事件等行为的回调方法
- fcsdwidget.FcsdWidgetImpl:福彩3D卡片管理类,提供了创建卡片、更新卡片、删除卡片、卡片点击事件等行为的回调方法
- ssqwidget.SsqWidgetImpl:双色球卡片管理类,提供了创建卡片、更新卡片、删除卡片、卡片点击事件等行为的回调方法
- controller
-
Constants:常量工具类
-
MainAbility:HAP的入口ability,由DevEco Studio自动生成。同时也是各个卡片对应的Ability,用来项各个FormController 分发事件
-
default
-
common
component/lottery:应用首页列表item组件
images :资源图片
-
pages
home:应用首页
-
-
dlt_widget
- common:资源图片存放目录
- pages/index
- index.css :大乐透卡片css样式
- index.hml:大乐透卡片布局文件
- index.json:包含页面默认值
-
fcsd_widget:目录结构同 dlt_widget
-
ssq_widget:目录结构同 dlt_widget
详细实现过程
1. 创建双色球卡片
在目录entry上点击右键,在弹出的菜单中选择New,然后在弹出的子菜单中点击Service Widget,如下图所示:
在模板选择界面,选择基本的模板Grid Pattern,点击按钮Next,进入到卡片配置界面
首先配置卡片的名称和描述;然后配置卡片关联的Page Ability;然后配置卡片的编程语言类型是JS;接下来配置卡片的JS组件名称;最后配置卡片支持的规格,勾选支持2x4、4x4规格
重复上述步骤,创建出大乐透和双色球卡片。运行项目,长按图标打开卡片管理界面,我们能看到刚创建的3类卡片,且每类卡片对应3种不同样式,如下图所示:
2. 绘制双色球卡片UI
我们编写双色球界面:
编写完成后,重新运行,不出意外你应该能看到如下效果:
这里提下卡片JS-UI框架的坑:
- 框架提供了原子布局来控制元素在不同尺寸布局上的隐藏和展示,但怎么说呢 ,一句话概括就是:你以为的并不是你以为的。可以看到我这里放弃了display-index的使用,而采用通过JAVA端卡片的类型,来适配不同的UI
- 不同于应用开发中的JS UI框架,这里的条件渲染 不支持表达式
- css 不支持标签选择器
- 部分css样式不能被继承,例如给父div元素设置了font-size,你会发现div中的text组件并没继承上述样式
- 列表渲染的for循环的数组必须是index.json data对象的最外层
- 不支持双层for循环
- api6 不兼容api 5的设备
你会发现卡片JSON文件中的data对象数据结构同接口返回的数据结构有些差异,就是因为上述原因导致的
3. 获取网络数据
简单的MVP架构,采用Retrofit+RxJava
作为异步网络请求框架
build.gradle
中添加RxJava和Retrofit的依赖:
config.json
文件中添加网络权限
创建接口请求:
P层和V层的接口比较简单,不在罗列。编写P层业务逻辑:
4. V层调用P层,更新卡片
这里提下MainAbility
的onCreateForm
方法,它在进入卡片管理界面时被调用,内部通过FormControllerManager
获取了卡片对应的FormController
,并调用了其bindFormData()
方法;由于我们卡片展示的数据来源于网络请求,在对应的FormController
实现类中不太好获得formId
,所以我们稍微改造一下FormController
的bindFormData
方法,把formId
给传进去
5. 简单的网络优化
由于onCreateForm(Intent intent)
方法会被调用多次,而每个类型的卡片请求的数据一样,聚合api一天100次免费请求的次数一会儿就用完了,故对此进行一个简单的优化:优先看内存缓存中是否有,有且为过期(缓存默认10分钟有效期)则直接返回,否则阻塞等待接口请求完成,对于并发请求,若请求队列已有相同的请求,则阻塞,否则创建新的请求。
若不关心接口调用的可略过本节。
6. 给卡片增加刷新事件和查看更多事件
给卡片的index.json
文件添加actions
,定义showMore为router事件,触发这个事件会跳转到指定的abilityName
对应的Ability;updateData
为message事件,触发该事件,会回调Ability中的onTriggerFormEvent(long formId, String message)
方法
卡片的布局文件中添加点击事件:
添加定时刷新:
打开config.json,对于标签“scheduledUpdateTime”设定的时刻,当到达之后,MainAbility中卡片的回调方法onUpdateForm()
就会被自动调用,updateDuration默认为1,下面配置表示:双色球卡片允许定时刷新,从10:30开始,每隔半小时刷新一次。
FormController
直接调用MainAbility
的获取数据方法
7. 大乐透和福彩3D卡片的实现
这两个卡片的实现过程和双色球卡片基本一致,主要是UI上有些区别。大乐透卡片4X4样式中,由于中奖信息列表较长,引入了list
和list-item
组件,让其可在卡片内上下滚动,具体实现此处不再赘述,有兴趣可阅读源码。
8.历史开奖列表的实现
这个界面也相对简单,使用了swiper
组件,左右滑动或点击头部标签栏,完成双色球、大乐透、福彩3D标签页的切换,每个标签页展示对应的近50期开奖结果,使用list
和list-item
组件渲染。由于各列表item展示UI相近,故将其抽成了组件放置于*/common/component/lottery*目录下。
lottery子组件部分
lottery.js
:通过props
接收外部传入的lotteryData数据
lottery.hml
组件布局代码:
css比较简单,这里不再给出
父组件实现:
尚未解决的问题:这里引入了http
组件进行网络请求,但在请求聚合接口时,失败率很高,但尝试请求别的网站的api时没有此现象,目前尚不知原因。
总结
由于这也是我第一次使用JS UI框架进行卡片开发的项目,水平有限,难免会对官方部分API理解不到位甚至理解有误的地方,希望大家也多多指正,共同进步。这一路上虽然磕磕巴巴,也有很多吐槽,但我们从卡片JS-UI API 5到API 6功能上逐渐靠拢应用JS-UI上也能看出来鸿蒙的努力,给它点时间,相信它功能上会变得更强大、完善;对于开发也会变得更快捷、简单。
最后附上项目地址:lottery-query
请自行下载资源,欢迎交流学习。
作者:熊文功
更多原创内容请关注:开鸿 HarmonyOS 学院
入门到精通、技巧到案例,系统化分享HarmonyOS开发技术,欢迎投稿和订阅,让我们一起携手前行共建鸿蒙生态。
老CM表示很赞。
彩票两元一注,剩下一元是私房钱吗?
我没有媳妇,如果捡到一元钱的话是不是就要就给警察叔叔了
和媳妇散步是捡钱的前提条件*-*,所有你需要先去找个媳妇。。。
这都被你发现了
ennnn... 没买过彩票的我,突然间有个想法 哈哈哈哈
巨佬,有代码地址嘛?想在手机上跑起来看看
文章末尾有代码地址哈。