作为 HarmonyOS 生态的开发者,入门阶段最适合通过 “实战项目” 巩固技术 —— 既能掌握 ArkTS 语法、UI 组件与 API 调用逻辑,又能产出可落地的小应用。本文将带大家从零开始,开发一款支持 “实时天气展示 + 未来 3 天预报” 的简易天气 APP,涵盖页面布局、网络请求、数据解析等核心开发环节,全程附规范代码与关键踩坑点,适合 HarmonyOS 开发新手参考学习。
一、项目前期准备:明确技术栈与核心需求
在动手前,先理清项目的 “技术边界” 与 “功能目标”,避免开发中频繁调整方向。
1. 技术栈选择
开发语言:ArkTS(基于 TypeScript 扩展,HarmonyOS 首选开发语言,语法更贴近前端,降低入门成本);
UI 框架:ArkUI(HarmonyOS 原生 UI 框架,采用 “声明式编程”,本文使用其基础组件如Column、Row、Text、Image等);
网络请求:使用 HarmonyOS 提供的@ohos.net.http模块(替代第三方库,减少依赖冲突);
数据来源:调用 “和风天气开放 API”(免费版可满足基础天气数据需求,需提前注册获取 API 密钥)。
2. 核心功能清单
页面 1(首页):展示当前城市、实时温度、天气状态(如 “晴”“多云”)、风向风力;
页面 2(预报页):以列表形式展示未来 3 天的日期、最高 / 最低温度、天气图标;
基础交互:首页点击 “查看预报” 按钮,跳转至预报页;预报页点击 “返回” 按钮,回到首页。
二、开发步骤拆解:从页面布局到功能实现
第一步:创建项目与配置权限
打开 DevEco Studio(本文使用 4.0 版本),新建 “Empty Ability” 项目,配置如下:
项目名称:WeatherApp;
包名:com.example.weatherapp(需符合 HarmonyOS 包名规范);
UI Syntax:ArkTS;
设备类型:默认支持 Phone(手机端)。
配置网络权限:由于需要调用外部 API,需在module.json5文件中添加网络访问权限,否则会出现请求失败:
json
{
"module": {
"abilities": [...],
"requestPermissions": [
{
"name": "ohos.permission.INTERNET" // 网络访问权限
}
]
}
}
第二步:实现首页(首页)UI 布局
首页采用 “垂直排列” 结构,从上到下依次为 “城市名称→实时温度→天气状态→功能按钮”,代码如下(路径:src/main/ets/pages/Index.ets):
typescript
import router from '@ohos.router'; // 导入路由模块,用于页面跳转
@Entry
@Component
struct Index {
// 定义页面状态变量(用于存储天气数据,初始值为空)
@State cityName: string = "北京市"
@State currentTemp: string = "25"
@State weatherStatus: string = "晴"
@State windInfo: string = "东北风 3级"
build() {
// 垂直布局容器,占满整个屏幕
Column({ space: 20 }) {
// 1. 城市名称
Text(this.cityName)
.fontSize(30)
.fontWeight(FontWeight.Bold)
.margin({ top: 50 })
// 2. 实时温度(大字体突出显示)
Text(`${this.currentTemp}°C`)
.fontSize(60)
.fontWeight(FontWeight.Bold)
// 3. 天气状态 + 风向风力
Column({ space: 10 }) {
Text(this.weatherStatus)
.fontSize(22)
Text(this.windInfo)
.fontSize(16)
.fontColor(Color.Gray)
}
// 4. 跳转按钮(点击跳转到预报页)
Button("查看未来3天预报")
.width(250)
.height(50)
.fontSize(18)
.backgroundColor("#007AFF")
.onClick(() => {
// 路由跳转:跳转到"Forecast"页面
router.pushUrl({
url: 'pages/Forecast'
})
})
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Top) // 内容靠上排列
.padding(20)
}
}
第三步:封装网络请求工具类
为避免代码冗余(首页和预报页都需要调用 API),单独封装一个 “天气数据请求工具类”,统一处理 API 调用、数据解析与错误捕获(路径:src/main/ets/utils/WeatherApi.ts):
typescript
import http from '@ohos.net.http';
// 和风天气API配置(需替换为自己的key)
const WEATHER_API_KEY = "你的和风天气API密钥";
const BASE_URL = "https://devapi.qweather.com/v7/weather";
export class WeatherApi {
/**
* 获取实时天气数据
* @param location 城市ID(如北京为"101010100",可从和风天气城市列表获取)
*/
static async getCurrentWeather(location: string): Promise {
let httpRequest = http.createHttp();
try {
// 1. 发起GET请求
const response = await httpRequest.request(
`${BASE_URL}/now?location=${location}&key=${WEATHER_API_KEY}`,
{ method: http.RequestMethod.GET }
);
// 2. 检查响应状态(200表示成功)
if (response.responseCode === 200) {
const result = JSON.parse(response.result.toString());
// 3. 检查API返回状态(和风天气返回code=200为成功)
if (result.code === "200") {
return result.now; // 返回实时天气数据
} else {
throw new Error(`API错误:${result.msg}`);
}
} else {
throw new Error(`网络错误:状态码${response.responseCode}`);
}
} catch (error) {
console.error("获取实时天气失败:", error);
throw error; // 抛出错误,让调用方处理
} finally {
// 4. 关闭请求(避免内存泄漏)
httpRequest.destroy();
}
}
/**
* 获取未来3天预报数据
* @param location 城市ID
*/
static async getForecastWeather(location: string): Promise {
let httpRequest = http.createHttp();
try {
const response = await httpRequest.request(
`${BASE_URL}/3d?location=${location}&key=${WEATHER_API_KEY}`,
{ method: http.RequestMethod.GET }
);
if (response.responseCode === 200) {
const result = JSON.parse(response.result.toString());
if (result.code === "200") {
return result.daily; // 返回未来3天数据(数组形式)
} else {
throw new Error(`API错误:${result.msg}`);
}
} else {
throw new Error(`网络错误:状态码${response.responseCode}`);
}
} catch (error) {
console.error("获取预报天气失败:", error);
throw error;
} finally {
httpRequest.destroy();
}
}
}
第四步:绑定数据到页面(实现 “数据驱动 UI”)
在首页Index.ets中调用工具类,获取实时天气数据,并更新页面状态变量(核心是使用aboutToAppear生命周期,页面加载前发起请求):
typescript
// 在Index.ets的struct Index中添加生命周期方法
aboutToAppear() {
// 页面加载前,获取实时天气数据(以北京为例,城市ID为101010100)
this.getCurrentWeatherData("101010100");
}
// 定义获取实时天气的方法
async getCurrentWeatherData(location: string) {
try {
const currentWeather = await WeatherApi.getCurrentWeather(location);
// 更新页面状态变量(ArkTS会自动触发UI刷新)
this.currentTemp = currentWeather.temp;
this.weatherStatus = currentWeather.text;
this.windInfo = `${currentWeather.windDir} ${currentWeather.windScale}级`;
} catch (error) {
// 错误处理:如网络失败时提示用户
promptAction.showToast({
message: "获取天气数据失败,请检查网络",
duration: 2000
});
}
}
// 注意:需在文件顶部导入promptAction(用于弹出提示)
import promptAction from '@ohos.promptAction';
第五步:实现预报页(Forecast.ets)
预报页以 “列表” 形式展示未来 3 天数据,核心是使用 ArkUI 的List组件循环渲染数据,代码如下(路径:src/main/ets/pages/Forecast.ets):
typescript
import router from '@ohos.router';
import { WeatherApi } from '../utils/WeatherApi';
import promptAction from '@ohos.promptAction';
@Entry
@Component
struct Forecast {
// 定义预报数据变量(数组类型,存储未来3天数据)
@State forecastList: Array = []
build() {
Column({ space: 15 }) {
// 1. 标题栏(含返回按钮)
Row({ space: 10 }) {
Button("← 返回")
.fontSize(18)
.backgroundColor("#007AFF")
.onClick(() => {
// 返回上一页
router.back();
})
Text("未来3天天气预报")
.fontSize(24)
.fontWeight(FontWeight.Bold)
}
.margin({ top: 30, bottom: 20 })
// 2. 预报列表
List() {
// 循环渲染预报数据
ForEach(this.forecastList, (item) => {
ListItem() {
Row({ space: 40 })
.width('100%')
.padding(15)
.backgroundColor("#F5F5F5")
.borderRadius(10) {
// 日期(如“2024-05-20”)
Text(item.fxDate)
.fontSize(18)
.width(120)
// 天气状态(如“晴”)
Text(item.textDay)
.fontSize(18)
.width(80)
// 最高温度
Text(`最高${item.tempMax}°C`)
.fontSize(18)
.width(100)
// 最低温度
Text(`最低${item.tempMin}°C`)
.fontSize(18)
.color(Color.Gray)
}
}
.margin({ bottom: 15 })
})
}
.width('100%')
}
.width('100%')
.height('100%')
.padding(20)
.justifyContent(FlexAlign.Top)
}
// 页面加载时获取预报数据
aboutToAppear() {
this.getForecastData("101010100");
}
async getForecastData(location: string) {
try {
const forecastData = await WeatherApi.getForecastWeather(location);
this.forecastList = forecastData; // 更新列表数据
} catch (error) {
promptAction.showToast({
message: "获取预报数据失败,请检查网络",
duration: 2000
});
}
}
}
三、关键踩坑点与优化建议
1. 常见错误与解决方案
问题现象 原因分析 解决方案
网络请求失败,控制台提示 “无 INTERNET 权限” 未在module.json5中配置网络权限 按步骤一添加ohos.permission.INTERNET权限
API 返回 “code=401” 和风天气 API 密钥错误或过期 登录和风天气官网,检查密钥是否正确,或重新申请
页面跳转时报 “url 不存在” 预报页Forecast.ets未在main_pages.json中注册 在src/main/ets/main_pages.json的 “src” 数组中添加"pages/Forecast"
2. 新手可做的优化方向
功能优化:添加 “城市选择” 功能(调用和风天气城市搜索 API,让用户手动切换城市);
UI 优化:替换天气状态为图标(如用 “☀️” 表示晴,“☁️” 表示多云,需提前准备图标资源);
体验优化:添加 “加载中” 提示(用Progress组件,在网络请求时显示,请求完成后隐藏);
数据缓存:使用@ohos.data.preferences模块缓存天气数据,避免每次打开 APP 都发起网络请求。
四、总结:从项目中掌握的核心知识点
通过本次简易天气 APP 开发,我们实际应用了 HarmonyOS 开发的多个核心技术:
ArkTS 语法:掌握@State状态管理(数据驱动 UI)、@Component组件定义、ForEach循环渲染;
ArkUI 组件:熟练使用Column/Row(布局)、List/ListItem(列表)、Button/Text(基础组件);
系统能力调用:学会使用http模块发起网络请求、router模块实现页面跳转、promptAction模块弹出提示;
工程化思维:理解 “工具类封装” 的意义(减少代码冗余)、“权限配置” 的必要性(保障 APP 正常运行)。
暂无评论数据
发布
相关推荐
1361
0
1656
0
没空恋爱的工程师
3658
0
鸿蒙小助手
6367
0雨季
计算机专业学生/从业者,深耕前端开发、C语言及CANN架构,熟系技术栈与工程实践,注重代码优化与问题拆解,以技术落地为核心,热衷AI应用与交互创新,持续精进创值。
帖子
提问
粉丝
《HarmonyOS 原子化服务开发实战:从卡片设计到 AI 意图调用》
2025-11-24 23:00:19 发布HarmonyOS 应用国际化开发指南:多语言适配与全球发布实战
2025-11-23 15:10:12 发布