鸿蒙5.0项目开发——鸿蒙天气项目的实现(主页1)
【高心星出品】
文章目录
- 页面效果:
- 页面功能:
- 页面执行流程:
- 1. 页面初始化阶段
- 2. 定位获取阶段
- 3. 天气数据加载阶段
这个页面是整个天气应用的核心,集成了天气查询、定位、搜索等主要功能,提供了完整的天气信息服务。
页面效果:
页面功能:
1. 天气信息展示
-
当前天气信息:
-
城市名称
-
温度
-
天气状况
-
湿度
-
风速
-
PM2.5
-
空气质量
-
未来天气预报:
-
显示未来3天的天气
-
包含星期、天气类型、温度范围
2. 定位功能
-
自动定位:
-
请求定位权限
-
获取当前位置
-
根据位置获取城市信息
-
显示当前位置天气
3. 搜索功能
-
城市搜索:
-
搜索框输入城市名
-
实时搜索天气信息
-
保存搜索历史
4. 搜索历史管理
-
历史记录功能:
-
显示搜索历史列表
-
支持删除单条记录
-
支持清空所有历史
-
点击历史记录可快速查看天气
5. 界面交互
-
左侧抽屉菜单:
-
显示搜索历史
-
支持滑动关闭
-
编辑模式切换
-
删除历史记录
6. 加载状态
-
加载提示:
-
显示加载动画
-
错误提示对话框
-
操作结果提示
7. 数据管理
-
数据持久化:
-
保存搜索历史
-
缓存天气数据
-
管理城市信息
8. 错误处理
-
异常处理:
-
网络错误提示
-
定位失败处理
-
数据加载失败处理
页面执行流程:
1. 页面初始化阶段
-
页面加载时触发 aboutToAppear 生命周期
-
首先检查定位权限
-
如果有权限,直接开启定位
-
如果没有权限,向用户请求权限
-
用户同意后开启定位,拒绝则使用默认城市(南京市)
-
/*** 组件即将出现时的生命周期函数* @description * 1. 首先请求定位权限* 2. 获取当前位置信息*/async aboutToAppear(): Promise<void> {// 请求定位权限await this.locationpermission()// 获取当前位置信息this.getlocation()}
/*** 请求定位权限* @description * 1. 创建权限管理器实例* 2. 获取应用程序的accessTokenID* 3. 校验应用是否被授予定位权限* 4. 如果未授权,则请求用户授权* 5. 根据用户授权结果执行相应操作*/async locationpermission() {// 创建权限管理器实例let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();// 初始化权限状态为拒绝let grantStatus: abilityAccessCtrl.GrantStatus = abilityAccessCtrl.GrantStatus.PERMISSION_DENIED;// 获取应用程序的accessTokenIDlet tokenId: number = 0;let bundleInfo: bundleManager.BundleInfo =await bundleManager.getBundleInfoForSelf(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION);let appInfo: bundleManager.ApplicationInfo = bundleInfo.appInfo;tokenId = appInfo.accessTokenId;// 校验应用是否被授予定位权限grantStatus = await atManager.checkAccessToken(tokenId, 'ohos.permission.APPROXIMATELY_LOCATION');if (grantStatus == abilityAccessCtrl.GrantStatus.PERMISSION_DENIED) {// 如果未授权,请求用户授权atManager.requestPermissionsFromUser(this.context, ['ohos.permission.APPROXIMATELY_LOCATION']).then((data) => {let grantStatus: Array<number> = data.authResults;if (grantStatus[0] === 0) {// 用户同意授权,修改lcc值触发lc函数执行this.lcc = 2} else {// 用户拒绝授权,弹窗提示AlertDialog.show({message: '您已拒绝授权定位,无法体验当前位置天气的信息功能',title: '提示',confirm: {value: '确定', action: () => {}}})}}).catch((e: Error) => {// 授权过程发生错误console.error('gxxt 授权', e.message)})} else {// 已有权限,设置lcc=1this.lcc = 1}}
2. 定位获取阶段
-
检查系统定位是否开启
-
如果已开启,直接获取位置
-
如果未开启,请求用户开启定位
-
-
获取当前位置信息
-
根据位置信息获取城市名称
-
如果获取失败,使用默认城市
/*** 获取位置信息* @description 根据定位权限状态决定是否开启定位* - 如果lcc=1表示有定位权限,则开启定位* - 否则直接加载默认城市天气*/getlocation() {if (this.lcc == 1) {// 开启定位this.openlocation()} else {this.loadweather(this.cityName, false)}}/*** 开启定位功能* @description 检查并请求开启系统定位功能* 1. 首先检查定位功能是否已开启* 2. 如果未开启,则请求用户开启* 3. 开启成功后调用locationreq()获取位置* 4. 开启失败则提示用户* @throws 可能抛出定位相关错误*/openlocation() {try {// 检查定位功能是否开启let enable = geoLocationManager.isLocationEnabled()if (!enable) {// 创建权限管理器let atmanager = abilityAccessCtrl.createAtManager()// 请求开启定位功能atmanager.requestGlobalSwitch(this.context, abilityAccessCtrl.SwitchType.LOCATION).then((value) => {if (value) { // 开启定位成功this.locationreq()} else { // 开启定位失败AlertDialog.show({message: '定位开启失败', title: '提示', confirm: {value: '确定',action: () => {}}})}})} else {// 定位已开启,直接获取位置this.locationreq()}} catch (e) {console.error('gxxt location ', JSON.stringify(e))}}/*** 获取定位城市信息* @description 通过系统定位服务获取当前位置并解析城市名称* 1. 首先显示加载动画弹窗* 2. 配置定位请求参数,优先考虑定位速度,超时时间10秒* 3. 调用getCurrentLocation获取经纬度坐标* 4. 根据经纬度反向解析获取城市名称* 5. 成功获取城市名称后加载该城市天气* 6. 失败则加载默认城市天气*/locationreq() {// 显示加载动画弹窗this.opendialog()// 配置定位请求参数let request: geoLocationManager.SingleLocationRequest = {'locatingPriority': geoLocationManager.LocatingPriority.PRIORITY_LOCATING_SPEED,'locatingTimeoutMs': 10000}// 获取当前位置geoLocationManager.getCurrentLocation(request).then((result) => {// 配置反向地理编码请求参数let reverseGeocodeRequest: geoLocationManager.ReverseGeoCodeRequest ={ "latitude": result.latitude, "longitude": result.longitude, "maxItems": 1 };// 根据经纬度获取地址信息geoLocationManager.getAddressesFromLocation(reverseGeocodeRequest, (err, data) => {if (err) {// 获取城市名称失败console.log('gxxt getAddressesFromLocation err: ' + JSON.stringify(err));promptAction.showToast({ message: '获取城市名称失败,请连接网络!' })// 加载默认城市天气this.loadweather(this.cityName, false)} else {// 获取城市名称成功,加载该城市天气this.loadweather(data[0].locality as string, false)}});}).catch((error: BusinessError) => {// 定位失败处理console.error('gxxt , getCurrentLocation: error=' + JSON.stringify(error));promptAction.showToast({ message: '无法获取地理位置' })// 加载默认城市天气this.loadweather(this.cityName, false)});}
3. 天气数据加载阶段
-
根据城市名称查询城市编码
-
使用城市编码获取天气数据
-
更新界面显示:
-
当前天气信息(温度、天气状况等)
-
未来三天天气预报
-
空气质量等信息
-
-
如果是搜索操作,保存搜索历史
/*** 加载天气信息* @param cityname 城市名称* @param issearch 是否是搜索请求* @description 根据城市名称加载天气信息* 1. 首先根据城市名称查询城市编码* 2. 使用城市编码获取天气数据* 3. 如果不是搜索请求则关闭加载弹窗* 4. 如果是搜索请求则保存搜索历史* 5. 更新页面上的天气信息显示* 6. 包括:城市名、温度、天气描述、湿度、风速、PM2.5、空气质量* 7. 更新未来3天的天气预报信息*/private async loadweather(cityname: string, issearch: boolean) {let ad = new adcodedao(this.context)try {// 查询城市编码let code = await ad.querybyname(cityname)// 获取天气数据let weather = await getweather(code)if (!issearch) {// 非搜索请求,关闭加载弹窗this.closedialog()} else {// 搜索请求,保存搜索历史let sd = new searchdao(this.context)sd.insert({ keyword: cityname })}// 更新城市基本信息this.cityName = weather.cityInfo.citythis.temperature = weather.data.wenduthis.weatherDesc = weather.data.forecast[0].typethis.humidity = weather.data.shiduthis.windSpeed = weather.data.forecast[0].flthis.pm25 = weather.data.pm25 + ''this.quality = weather.data.quality// 更新未来3天天气预报this.day1week = weather.data.forecast[1].weekthis.day1type = weather.data.forecast[1].typethis.day1wendu = getwendu(weather.data.forecast[1].low, weather.data.forecast[1].high)this.day2week = weather.data.forecast[2].weekthis.day2type = weather.data.forecast[2].typethis.day2wendu = getwendu(weather.data.forecast[2].low, weather.data.forecast[2].high)this.day3week = weather.data.forecast[3].weekthis.day3type = weather.data.forecast[3].typethis.day3wendu = getwendu(weather.data.forecast[3].low, weather.data.forecast[3].high)} catch (e) {// 显示错误提示对话框AlertDialog.show({message: '该地区天气信息暂无法获取!', title: '提示', confirm: {value: '确定', action: () => {}}})}}
根据城市名称查询城市编码:
/*** 根据城市名称查询城市编码* @param name 城市名称* @returns 城市编码* @description * 1. 根据城市名称模糊查询数据库* 2. 只查询code字段* 3. 如果查询到结果则返回城市编码* 4. 如果查询失败则返回空字符串*/async querybyname(name: string) {let code: string = ''try {let rdb = await getrdb(this.context)let predicates = new relationalStore.RdbPredicates(TABLENAME)predicates.like('name', '%' + filter(name) + '%')let rs = await rdb.query(predicates, ['code'])if (rs.goToNextRow()) {code = rs.getString(rs.getColumnIndex('code'))}} catch (e) {console.error('gxxt adcodedao 查询失败: ', JSON.stringify(e))}return code}
使用城市编码获取天气数据
/*** 天气API的基础URL*/
export const BASEURL = 'http://t.weather.itboy.net/api/weather/city/'/*** 获取城市天气信息* @param citycode 城市编码* @returns Promise<weathermodel> 返回天气数据模型* @description * 1. 根据城市编码拼接完整的API URL* 2. 创建HTTP请求实例* 3. 配置请求头为JSON格式* 4. 发送GET请求获取天气数据* 5. 解析响应数据为weathermodel类型* 6. 如果状态码为200则返回数据* 7. 否则抛出错误* 8. 最后销毁HTTP请求实例*/
export function getweather(citycode: string) {let url = BASEURL + citycodelet req = http.createHttp()let opt: http.HttpRequestOptions = {header: {'Content-Type': 'application/json;charset=UTF-8'}}return new Promise<weathermodel>((resove, reject) => {req.request(url, opt).then((res) => {let data =JSON.parse( res.result as string) as weathermodelif(data.status==200) {resove(data)}else{reject('不在范围之内')}}).catch((e: Error) => {reject(e)}).finally(() => {req.destroy()})})}
相关文章:

鸿蒙5.0项目开发——鸿蒙天气项目的实现(主页1)
【高心星出品】 文章目录 页面效果:页面功能:页面执行流程:1. 页面初始化阶段2. 定位获取阶段3. 天气数据加载阶段 这个页面是整个天气应用的核心,集成了天气查询、定位、搜索等主要功能,提供了完整的天气信息服务。 …...
python项目参考文献
技术范围:SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论文…...

【ESP32】ESP-IDF开发 | 低功耗蓝牙开发 | GATT规范和ATT属性协议 + 电池电量服务例程
1. 简介 低功耗蓝牙中最为核心的部分当属 GATT(Generic Attribute Profile),全称通用属性配置文件。而 GATT 又是建立在 ATT 协议(属性协议)的基础之上,为 ATT 协议传输和存储的数据建立了通用操作和框架。…...

2025 年九江市第二十三届中职学校技能大赛 (网络安全)赛项竞赛样题
2025 年九江市第二十三届中职学校技能大赛 (网络安全)赛项竞赛样题 (二)A 模块基础设施设置/安全加固(200 分)A-1 任务一登录安全加固(Windows,Linux)A-2 任务二 Nginx 安全策略&…...

【记录】Windows|竖屏怎么调整分辨率使横竖双屏互动鼠标丝滑
本文版本:Windows11,记录一下,我最后调整的比较舒适的分辨率是800*1280。 文章目录 第一步 回到桌面第二步 右键桌面第三步 设置横屏为主显示器第四步 调整分辨率使之符合你的需求第五步 勾选轻松在显示器之间移动光标第六步 拖动屏幕符合物理…...

开源项目实战学习之YOLO11:12.2 ultralytics-models-sam-decoders.py源码分析
👉 点击关注不迷路 👉 点击关注不迷路 👉 另外,前些天发现了一个巨牛的AI人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。感兴趣的可以点击相关跳转链接。 点击跳转到网站。 ultralytics-models-sam 1.sam-modules-decoders.pyblocks.py: 定义模型中的各…...

数据结构*优先级队列(堆)
什么是优先级队列(堆) 优先级队列一般通过堆(Heap)这种数据结构来实现,堆是一种特殊的完全二叉树,其每个节点都满足堆的性质。如下图所示就是一个堆: 堆的存储方式 由于堆是一棵完全二叉树,所以也满足二…...

汽车Wafer连接器:工业设备神经网络的隐形革命者
汽车Wafer连接器正在突破传统车载场景的边界,以毫米级精密结构重构工业设备的连接范式。这款厚度不足3毫米的超薄连接器,在新能源电池模组中承载200A持续电流的同时,仍能保持85℃温升的稳定表现,其每平方厘米高达120针的触点密度&…...

微信小程序:封装表格组件并引用
一、效果 封装表格组件,在父页面中展示表格组件并显示数据 二、表格组件 1、创建页面 创建一个components文件夹,专门用于存储组件的文件夹 创建Table表格组件 2、视图层 (1)表头数据 这里会从父组件中传递表头数据,这里为columns,后续会讲解数据由来 循环表头数组,…...
湖北理元理律师事务所:债务优化中的双维支持实践解析
在债务压力与生活质量失衡的社会议题下,法律服务机构的功能边界正在从单一的法律咨询向复合型支持延伸。湖北理元理律师事务所通过“法律心理”双维服务模式,探索债务优化与生活保障的平衡路径,其方法论或为行业提供实践参考。 法律框架&…...
uniapp在APP上如何使用websocket--详解
UniApp 在 APP 端如何使用 WebSocket以及常见问题 一、WebSocket 基础概念 WebSocket 是一种在单个TCP连接上进行全双工通信的协议,适用于实时数据传输场景(如聊天室、实时游戏、股票行情等)。 与传统HTTP对比 特性WebSocketHTTP连接方式…...
计网| 网际控制报文协议(ICMP)
目录 网际控制报文协议(ICMP) 一、ICMP 基础特性 二、ICMP 报文分类及作用 差错报告报文 询问报文 网际控制报文协议(ICMP) ICMP(Internet Control Message Protocol,网际控制报文协议)是 …...

Conda 完全指南:从环境管理到工具集成
Conda 完全指南:从环境管理到工具集成 在数据科学、机器学习和 Python 开发领域,环境管理一直是令人头疼的问题。不同项目依赖的库版本冲突、Python 解释器版本不兼容等问题频繁出现,而 Conda 的出现彻底解决了这些痛点。作为目前最流行的跨…...

安卓中0dp和match_parent区别
安卓中的 0dp 和 match_parent 的区别? 第一章 前言 有段时间,看到同事在编写代码的时候,写到的是 0dp 有时候自己写代码的时候,编写的是 match_parent 发现有时候效果很类似。 后来通过一个需求案例,才发现两者有着…...
蓝桥杯-不完整的算式
问题描述 小蓝在黑板上写了一个形如 AopBCAopBC 的算式,其中 AA、BB、CC 都是非负整数,opop 是 、-、*、/、-、*、/(整除)四种运算之一。不过 AA、opop、BB、CC 这四部分有一部分被不小心的同学擦掉了。 给出这个不完整的算式&a…...

信贷风控笔记4——贷前策略之额度、定价(面试准备12)
1.贷前模型的策略应用 分类:审批准入(对头尾部区分度要求高):单一规则(找lift>3的分数做规则);二维交叉;拒绝回捞 额度定价(对排序性要求高)&am…...

A级、B级弱电机房数据中心建设运营汇报方案
该方案围绕A 级、B 级弱电机房数据中心建设与运营展开,依据《数据中心设计规范》等标准,施工范围涵盖 10 类机房及配套设施,采用专业化施工团队与物资调配体系,强调标签规范、线缆隐藏等细节管理。运营阶段建立三方协同运维模式,针对三级故障制定30 分钟至 1 小时响应机制…...

Linux中的域名解析服务器
一、DNS(域名系统)详解 1. 核心功能与特点 特性说明核心作用将域名(如 www.example.com)转换为 IP 地址(如 192.168.1.1),实现人类可读地址与机器可读地址的映射。端口与协议- 默认端口&#…...
如何优化Java中十进制字符串转十六进制的性能
在 Java 中优化十进制字符串转十六进制的性能,可以从减少对象创建、避免正则表达式、使用高效数据结构等方面入手。以下是具体的优化方案: 1. 避免字符串分割,直接遍历字符数组 原始方法(频繁创建子字符串)࿱…...

CycleISP: Real Image Restoration via Improved Data Synthesis通过改进数据合成实现真实图像恢复
摘要 大规模数据集的可用性极大释放了深度卷积神经网络(CNN)的潜力。然而,针对单图像去噪问题,获取真实数据集成本高昂且流程繁琐。因此,图像去噪算法主要基于合成数据开发与评估,这些数据通常通过广泛假设的加性高斯白噪声(AWGN)生成。尽管CNN在合成数据集上表现优异…...

Day28 Python打卡训练营
知识点回顾: 1. 类的定义 2. pass占位语句 3. 类的初始化方法 4. 类的普通方法 5. 类的继承:属性的继承、方法的继承 作业 题目1:定义圆(Circle)类 要求: 1. 包含属性:半径 radius。 2. …...
【OpenCV】基本数据类型及常见图像模式
是什么?能做什么?解决什么问题?为什么用它? OpenCV:是一个基于开源发行的跨平台计算机视觉库,实现 一、应用场景: 目标识别:人脸、车辆、车牌...自动驾驶医学影像分析视频内容理解与分析&…...

Linux之Nginx安装及配置原理篇(一)
Nginx安装及配置 前情回顾 首先针对Nginx进程模型,我们回顾一下它的原理机制,我们知道它是通过Master通过fork分发任务节点给予work节点,然后work节点触发了event事件,之后通过一个access_muttex互斥锁,来单线程调用我…...

【Linux网络】NAT和代理服务
NAT 之前我们讨论了,IPv4协议中,IP地址数量不充足的问题。 原始报文途径路由器WAN口时,对报文中的源IP进行替换的过程,叫做NAT。 NAT技术当前解决IP地址不够用的主要手段,是路由器的一个重要功能: NAT能…...

中药药效成分群的合成生物学研究进展-文献精读130
Advances in synthetic biology for producing potent pharmaceutical ingredients of traditional Chinese medicine 中药药效成分群的合成生物学研究进展 摘要 中药是中华民族的文化瑰宝,也是我国在新药创制领域的重要驱动力。许多中药材来源于稀缺物种…...

【消息队列】RabbitMQ基本认识
目录 一、基本概念 1. 生产者(Producer) 2. 消费者(Consumer) 3. 队列(Queue) 4. 交换器(Exchange) 5. 绑定(Binding) 6. 路由键(Routing …...
OCCT知识笔记之OCAF框架详解
OCAF框架在OCCT项目中的构建与使用指南 Open CASCADE Application Framework (OCAF)是Open CASCADE Technology (OCCT)中用于管理CAD数据的核心框架,它提供了一种结构化方式来组织和管理复杂的CAD数据,如装配体、形状、属性(颜色、材料)和元数据等。本文…...
蓝桥杯 16. 外卖店优先级
外卖店优先级 原题目链接 题目描述 “饱了么” 外卖系统中维护着 N 家外卖店,编号 1 ∼ N。每家外卖店都有一个优先级,初始时(0 时刻)优先级都为 0。 每经过 1 个时间单位: 如果外卖店没有订单,则优先…...

1T 服务器租用价格解析
服务器作为数据存储与处理的核心设备,对于企业和个人开发者而言至关重要。当涉及到租用 1T 服务器时,价格是大家很为关注的要点。然而,1T 服务器租用一个月的费用并非固定不变,而是受到诸多因素的综合影响。 影响 1T 服务器租用…...

【JavaWeb】Maven(下)
1 依赖管理 1.1 依赖配置 1.1.1 基本配置 依赖:指当前项目运行所需要的jar包。 一个项目中可以引入多个依赖: 例如:在当前工程中,我们需要用到logback来记录日志,此时就可以在maven工程的pom.xml文件中,引…...