鸿蒙NEXT开发浅进阶到精通14:鸿蒙开发项目中遇到的需求问题及解决笔记05
写在前面
很久没有更新笔记啦,日子好快,眼看就要国庆节2025还剩1/4啊,最近在忙公司一些项目的鸿蒙端开发和管理台的开发中,我们做了一些批量构建元服务的操作,让我对鸿蒙的底层产生了很大兴趣,也是我们往往会做事情直奔主题,开发应用端就开发应用端,但一位Java老哥在 公司里被主管催着学鸿蒙,据我的采访他是看了官网的鸿蒙基础课和文档里的一些底层介绍,再比着敲一个项目,就上手了,做出来的一个甲方鸿蒙化项目,也很专业,调用了鸿蒙新特性以及手机能力。但在打包盒制作签名方面可能实战少,略逊我一瞅哈哈。在我看RN的时候,他也给出 建议一开始不要着急,要多看文档和RN官网的介绍,比如新建一个RN项目等基础信息。我的编程启蒙老师也说过学编程要有耐心,最重要的是查看文档的能力,不然学是学不完的开发某语言要学会看懂官网的文档,这样才有可能持续的做出好的项目,其实后面想做一些官网文档解读系列的博客,不知道各位鸿友们是否有兴趣。
好了看下这两个月我又在项目中遇到了什么值得留笔记的实战需求与知识点吧。
一、代码内改变在线图片的宽度像素,提高加载效率
我们很多正式项目中的图片大多数都是后端服务器或obs中的图片直接返回给我们,这里有些需要注意的点,就是其他工程师小伙伴要处理一下保证清晰度和图片大小,首先是解决obs内存占用效率的问题,还有就是我们前端手机端的加载问题。当然好在我们鸿蒙有懒加载,但对应对象或者短列表也没必要,那么怎么能让图片组件占位图快点消失,这个就很有用。以下方法仅适用于在线url,string类型,场景在商品卡片中,但如果这个图片是可以点击预览的,那么在预览逻辑里就不要这样使用了,因为多少会影响画面清晰度,但对于头像,商品列表缩略图等小尺寸展示时,很好用凹。
//在内层滚动容器上添加nestedScroll,根据业务需要调整滚动优先级
export function addCustmerWidth(url:string,custWidth:number=400){if (url) {if (url.includes('?')) {if (url.includes(`x-oss-process=image/resize,w_${custWidth}`)) {return url}else {return url + `&x-oss-process=image/resize,w_${custWidth}`}}else {return url + `?x-oss-process=image/resize,w_${custWidth}`}}else {return ''}
}Image(addCustmerWidth(imageItem))
这里我们处理的第一核心是图片组件中的url+?x-oss-process=image/resize,w_${custWidth}
指定尺寸,不过考虑到原url是否已经加了尺寸,所以我做了一个封装函数来避免尺寸参数重复。
含金量很足,看起来是一些if else操作,其实是考虑的比较全面,也是一种思路。如果有更好的封装方式,欢迎交流哈。
二、api18简约弹框
这里为啥我会留个API18呢,因为我从24年初接触鸿蒙那时候才API11在初期的正式项目中大多数是11和12,其实鸿蒙发展迅速,目前很正式的版本是19,API20是鸿蒙6是bate版,我在提醒自己不能吃老本,在最近的项目中就是“老”项目的二次利用但有很多废弃代码,有时候没有影响功能,但有时候会稍有影响,这个弹框就是其中一个例子。
let promptAction: PromptAction = this.getUIContext().getPromptAction();
try {promptAction.showDialog({title: '删除后将不能查阅到此订单',message: '请确认是否删除',buttons: [{text: '取消',color: '#000000'},{text: '确认',color: '#EE7529'}]}, (err, data) => {if (err) {console.error('showDialog err: ' + err);return;}console.info('showDialog success callback, click button: ' + data.index);});
} catch (error) {let message = (error as BusinessError).message;let code = (error as BusinessError).code;console.error(`showDialog args error code is ${code}, message is ${message}`);
};
大家有使用这里的时候可以看一下。
三、image组件跨模块取图片资源
我们常见的项目大多数是单模块的,但熟悉三层架构开发的小伙伴,比较熟悉“模块”这个名词,其实是我们之前对复用比较高的组件结构不再封装成一个组件ets文件了,而是对与单个功能封装进一个hap包里或hsp包,在项目中引用,如果是同一个公司的话,这个本地hap包可以直接复制到其他项目中,提高开发效率。比如我的模块,地址模块,还有分功能便于维护的,比如我们最近一个新项目是分了运动模块,喝水模块等等。
那么本地项目含有两个以上,用引用同一张图片,总不能每个地方的图片资源文件夹里我们都复制进去一张吧,那样会增加项目包的体积,要知道元服务打包不能超过2M的限制一直在凹。
注意,可以取到,但资源删除时这里不报错,运行时也不报错仅不展示对应图片,这在使用中比较危险,因为你在删除某种resource中的图片时,及时开启了安全检查,这里因为前面加了common模块名,而不是‘app’这个检测中判断关键词,他不会去判断后面的文件名了。所以谨慎使用。
四、在线视频video组件视频获取第一帧做封面
Video({
src: url,
previewUri:'',
currentProgressRate: this.curRate,
controller: this.controller
})
.width(BusinessDetailStyleConstants.FULL_PERCENT)
.objectFit(ImageFit.Cover)
.aspectRatio(1)
.borderRadius(BusinessDetailStyleConstants.DETAIL_IMG_VIDEO_CARD_BORDER_RADIUS)
.onPrepared(() => {
if (this.firstTime) {this.firstTime = falsethis.controller.setCurrentTime(0)this.controller.start()setTimeout(()=>{this.controller.stop()}, 50)
}
})
其实是让其(自动)播放但在开始的时候就暂停,这个方法有点取巧,适用于这个页面就这一个视频组件的情况,但对应视频列表不能使用,因为要增加多个视频播放控制器,这个难度较大,而且也会消耗性能,很没有必要,跟后端说一下给传个封面图片url字段来,使用Video组件的previewUri属性即可。当然也要协调项目管理台增加一个封面上传功能。很体现协作性(如果好沟通的haul)
字符串去掉空格-正则表达式替换
没啥好说的,用到就用到了
// 示例:去除字符串中的所有换行符 \n
let originalStr: string = "Hello\nWorld\nWelcome to HarmonyOS!";
let cleanedStr: string = originalStr.replace(/\n/g, '');// 输出结果
console.log(cleanedStr); // 输出: "HelloWorldWelcome to HarmonyOS!"
文本字间距Text
在展示校验码纯数字或字母数字展示时,控制字间距,满足UX设计要求。其实在鸿蒙开发中大多数程序员对Text这个基础组件的使属性了解的不足10%,很有深度的一个基础组件。
// 文本字符间距 .letterSpacing(5)Text('This is the text content with letterSpacing 0.').letterSpacing(5).margin(10)Text('0927 0317').letterSpacing(5).fontWeight(500).fontSize(20).margin(10)
长字符串中间…省略号样式
这个在订单号的展示或者下载列表中比较常见,因为我们随机生成的订单号或者临时下载的文件名都很长,屏幕就那么宽,对于文件名的展示,当然是留住两头,中间省略,对于大多数的产品逻辑,订单号的前几位是时间后几位比较有识别性。
不过呢在CV借鉴我这段代码的时候要注意.ellipsisMode(EllipsisMode.CENTER)属性他是针对当前字符串的中间进行省略。可以看下示意图的第一个订单号,日期没有漏出来,因为他把【订单号】也算在长度里了。可以参考第二行的代码效果。
Text(`订单号: `+'202509271111hhsdskdsah08736346464').maxLines(1).textOverflow({overflow: TextOverflow.Ellipsis}).ellipsisMode(EllipsisMode.CENTER).width('50%')// .layoutWeight(1) //根据情况使用,最重要的是要有指定宽度或者相对宽度,不然textOverflow没有大的意义.margin(10)Row(){Text('订单号: ')// .layoutWeight(1) //根据情况使用,最重要的是要有指定宽度或者相对宽度,不然textOverflow没有大的意义.margin(10)Text('202509271111hhsdskdsah08736346464').maxLines(1).textOverflow({overflow: TextOverflow.Ellipsis}).ellipsisMode(EllipsisMode.CENTER)// .width('50%').layoutWeight(1) //根据情况使用,最重要的是要有指定宽度或者相对宽度,不然textOverflow没有大的意义.margin(10)}.width('80%')
如果你的项目是多模块架构,最好一开始就规范起来用后者,避免打出测试包或者上架审核时出现跳转模块异常的问题,耽误项目进度。
五、 主动退出app、元服务,并去掉这个app的后台任务
这个比较实用,在初期鸿蒙开发中,还没有隐私政策与用户协议的托管,我们在展示这个模块的时候不仅要自己开发UI代码,而且还要注意用户点击不同意,是不能进入主页面进行操作的,而是直接跳出,当时我只看到了这个 跳出,还可以进一步配置连后台任务也清掉,因为我最近有个需求就是用户注销时,我们要退回到桌面,然后清理这个任务。
this.context.terminateSelf().then(() => {// 执行正常业务-可跟可不跟console.info('terminateSelf succeed');}).catch((err: BusinessError) => {// 处理业务逻辑错误console.error(`terminateSelf failed, code is ${err.code}, message is ${err.message}`);});
(可选)如果需要在停止UIAbility时,清理任务中心的相关任务(即不保留最近任务列表中的快照),需要在module.json5配置文件中将removeMissionAfterTerminate字段取值配置为true。
{"module": {// ..."abilities": [{// ..."removeMissionAfterTerminate": true}]}
}
写在后面
好啦,最近的很值得留的笔记又更新完啦,祝大家开发愉快,最近官方的激励计划,奖金挺丰厚,有开发app或者元服务想法的小伙伴不要错过上架哦。奖金5000起哈哈,就是现在我手头太忙了,上班回家腰已经不再支持我坐在电脑桌前了,趴床上敲过一段时间,但是也挺费肩膀和肘子的。能者多捞吧。祝君好运。
另外我已经申请通过了鸿蒙讲师认证,开设了一个鸿蒙班级,有兴趣的小伙伴可以加入我的班级凹,https://developer.huawei.com/consumer/cn/training/classDetail/c63ac2094b15446f8b3a90d8ea78052e?type=1?ha_source=hmosclass&ha_sourceId=89000248 (加入时会让填学号,大家可以留写自己的华为账号手机号什么的避免重复); 这个主要是官方带动鸿蒙基础、高级开发认证的,这个认证考试还是要自己多看的,我可以提供些经验和额外的福利,可以平常看一下大家开发中遇到的问题等。对于新上手鸿蒙开发的友友,也会有些进阶指导。