# ArkStageWeatherDemo **Repository Path**: jltx/ark-stage-weather-demo ## Basic Information - **Project Name**: ArkStageWeatherDemo - **Description**: 基于鸿蒙ArkTS语言Stage模型构建的天气应用Demo。使用了Lottie动画库。 - **Primary Language**: Unknown - **License**: GPL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 3 - **Created**: 2024-06-27 - **Last Updated**: 2024-06-27 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # ArkStageWeatherDemo #### 项目地址 项目已经上传到Gitee,欢迎各位开发者阅读及批判。 #### 介绍 Intro 基于鸿蒙ArkTS语言Stage模型构建的天气应用Demo。使用了Lottie动画库。 Build the app based on the OpenHarmony ArkTS language and the Stage model. Achieve the basic functions of a weather application. ![img_.png](./image/demo.gif) #### 软件架构 Software Achitechture 项目文件目录如下所示: ``` ArkStageWeatherDemo ├─entry // 程序入口 │ └─src │ ├─main │ │ ├─ets │ │ │ ├─common │ │ │ │ ├─bean // 项目相关 bean 对象文件夹 │ │ │ │ ├─constants // 常量文件夹 │ │ │ │ ├─lottie // Lottie 动画 JSON 文件夹 │ │ │ │ └─utils // 工具类文件夹 │ │ │ │ └─log // 日志工具文件夹 │ │ │ ├─entryability // 程序入口 │ │ │ ├─pages // 相关页面 │ │ │ ├─view // 相关视图 │ │ │ └─viewmodel // 相关viewmodel │ │ └─resources │ │ └─base │ │ ├─element │ │ ├─media │ │ └─profile │ └─ohosTest │ └─MyWeather // 本地天气库 - MyWeather └─src └─main ├─ets │ ├─bean // 天气相关 bean 对象文件夹 │ ├─client // 天气请求客户端类文件夹 │ └─constants // 常量文件夹 └─resources └─base └─element ``` 可以发现程序主要由两部分组成: - **entry** - 作为程序的主入口,程序的页面及相关逻辑都在此 module 下; - **MyWeather** - 天气请求本地库,基于“和风天气”封装了天气请求,使得其他module可以通过调用该模块对外提供的接口实现天气相关信息获取。 此外,程序还使用到了`@ohos/lottieETS`外部库,用于播放天气动画。 #### 本地库 MyWeather 封装 为了便于调用天气接口,实现适当的解耦,讲天气访问功能进行了抽取,封装成`MyWeather`本地库。截图如下: ![](./image/MyWeather.png) 核心代码如下: ##### 实况天气请求 ```typescript /** * NowWeatherClient.ets * 实况天气请求 */ import http from '@ohos.net.http'; import { NowWeatherBean } from "../bean/NowWeatherBean"; import { MyWeatherConstants } from "../constants/Constants" export class NowWeatherClient { /** * 天气请求 KEY */ private api_key: string = ""; /** * 构造方法 * * @param apiKey 天气请求 KEY */ constructor(apiKey: string) { this.api_key = apiKey; } /** * 异步获取实时天气数据 * * @param cityId 城市 ID,需传入所要查看天气城市的 ID * @param callback 请求回调,将回调一个 NowWeatherBean 对象 */ public getNowWeatherData(cityId: string, callback: (bean: NowWeatherBean) => any) { let bean = null; if (cityId.length == 0) { callback(bean) } // 实例化 httpRequest 对象 let httpRequest = http.createHttp(); // 订阅 http 响应头 httpRequest.on('headersReceive', (header) => { console.info('ZJH: header: ' + JSON.stringify(header)); }); // 发起 http 请求 httpRequest.request( this.buildRequestUrl(cityId), (err, data) => { if (!err) { console.info('ZJH: Result:' + data.result); console.info('ZJH: Result type: ' + typeof data.result); console.info('ZJH: code:' + data.responseCode); // 解析响应,获取 NowWeatherBean 对象 bean = this.parseNowWeather(data.result as string); httpRequest.destroy(); // 解析成功,回调 NowWeatherBean 对象到外部 callback(bean); } else { console.info('ZJH: error:' + JSON.stringify(err)); httpRequest.destroy(); callback(bean); } } ); } private buildRequestUrl(cityId: string): string { let finalUrl = MyWeatherConstants.URL_NOW_WEATHER + "?key=" + this.api_key + "&location=" + cityId; return finalUrl; } private parseNowWeather(nowWeatherData: string): NowWeatherBean { console.info('ZJH: parseNowWeather: nowWeatherData:' + nowWeatherData); let bean: NowWeatherBean = JSON.parse(nowWeatherData); console.info('ZJH: parseNowWeather: nowWeatherData2:' + bean.now.text); console.info('ZJH: parseNowWeather: nowWeatherData2:' + bean.now.temp); console.info('ZJH: parseNowWeather: nowWeatherData2:' + bean.now.windSpeed); return bean; } } ``` ##### 三日天气预报请求 ```typescript /** * ThreeDayWeatherClient.ets * 三日天气预报请求 */ import http from '@ohos.net.http'; import { ThreeDayWeatherBean } from "../bean/ThreeDayWeatherBean"; import { MyWeatherConstants } from "../constants/Constants" export class ThreeDayWeatherClient { /** * 天气请求 KEY */ private api_key: string = ""; /** * 构造方法 * * @param apiKey 天气请求 KEY */ constructor(apiKey: string) { this.api_key = apiKey; } /** * 异步获取实时天气数据 * * @param cityId 城市 ID,需传入所要查看天气城市的 ID * @param callback 请求回调,将回调一个 NowWeatherBean 对象 */ public getThreeDayWeatherData(cityId: string, callback: (bean: ThreeDayWeatherBean) => any) { let bean = null; if (cityId.length == 0) { callback(bean) } // 实例化 httpRequest 对象 let httpRequest = http.createHttp(); // 订阅 http 响应头 httpRequest.on('headersReceive', (header) => { console.info('ZJH: header: ' + JSON.stringify(header)); }); // 发起 http 请求 httpRequest.request( this.buildRequestUrl(cityId), (err, data) => { if (!err) { console.info('ZJH: Result:' + data.result); console.info('ZJH: Result type: ' + typeof data.result); console.info('ZJH: code:' + data.responseCode); // 解析响应,获取 NowWeatherBean 对象 bean = this.parseThreeDayWeather(data.result as string); httpRequest.destroy(); // 解析成功,回调 NowWeatherBean 对象到外部 callback(bean); } else { console.info('ZJH: error:' + JSON.stringify(err)); httpRequest.destroy(); callback(bean); } } ); } private buildRequestUrl(cityId: string): string { let finalUrl = MyWeatherConstants.URL_THREE_DAY_WEATHER + "?key=" + this.api_key + "&location=" + cityId; return finalUrl; } private parseThreeDayWeather(threeDayWeatherData: string): ThreeDayWeatherBean { console.info('ZJH: parseThreeDayWeather: threeDayWeatherData:' + threeDayWeatherData); let bean: ThreeDayWeatherBean = JSON.parse(threeDayWeatherData); return bean; } } ``` ##### 天气数据统一单例入口类 ```typescript /** * MyWeather.ets * 模块入口,单例,外界通过调用该类可以进行各种天气信息的访问 */ import { NowWeatherBean } from "./bean/NowWeatherBean"; import { NowWeatherClient } from "./client/NowWeatherClient"; import { ThreeDayWeatherBean } from "./bean/ThreeDayWeatherBean"; import { ThreeDayWeatherClient } from "./client/ThreeDayWeatherClient"; export class MyWeather { /** * 单例模式私有实例 */ private static instance: MyWeather; /** * 天气请求 KEY */ private api_key: string = ""; /** * 私有构造方法 */ private constructor() { } /** * 获取当前类实例,懒加载 */ public static getInstance() { if (this.instance == null) { this.instance = new MyWeather(); } return this.instance; } /** * 初始化当前 Client,目前作用是为 Client 设置请求 API KEY * * @param apiKey 天气请求 API KEY */ public init(apiKey: string) { this.api_key = apiKey; } /** * 异步获取实时天气数据 * * @param cityId 城市 ID,需传入所要查看天气城市的 ID * @param callback 请求回调,将回调一个 NowWeatherBean 对象 */ public getNowWeatherData(cityId: string, callback: (bean: NowWeatherBean) => any) { let nowWeatherClient = new NowWeatherClient(this.api_key); nowWeatherClient.getNowWeatherData(cityId, callback); } /** * 异步获取三日天气预报数据 * * @param cityId 城市 ID,需传入所要查看天气城市的 ID * @param callback 请求回调,将回调一个 NowWeatherBean 对象 */ public get3DayWeatherData(cityId: string, callback: (bean: ThreeDayWeatherBean) => any) { let threeDayWeatherClient = new ThreeDayWeatherClient(this.api_key); threeDayWeatherClient.getThreeDayWeatherData(cityId, callback); } } ``` #### 后续优化 目前的效果只是一个简单的最小功能实现,只是能够以较为简陋的方式展示固定5个城市的实况天气和3天天气预报,无法允许用户自行选择城市,也没有实现实时刷新和缓存等功能,后续考虑从以下几个方面继续优化: 1. 增加城市列表添加和删除城市功能; 2. 增加缓存功能,缓存天气数据以降低对服务器的压力; 3. 增加定时刷新功能,确保天气的相对准确性; 4. 增加下拉刷新功能,允许用户手动刷新当前城市天气。