新手学习全过程实录06——零基础搭建鸿蒙天气应用
️ 新手学习 ArkUI 全过程实录——零基础搭建鸿蒙天气应用一、前言为什么现在必须学 ArkUI2024 年 10 月华为正式发布了HarmonyOS NEXT鸿蒙星河版这个版本彻底移除了 AOSP 代码不再兼容 Android APK。所有鸿蒙原生应用必须用ArkTS ArkUI重新开发。这对开发者意味着什么蓝海窗口期鸿蒙设备量已破 8 亿但原生应用数量还远不够现在入局就是早期红利。声明式 UI 是未来ArkUI 的声明式语法和 SwiftUI、Jetpack Compose 同源学一个顶三个。开发体验好DevEco Studio 基于 IntelliJ写代码、预览、调试一气呵成。但我坦白我刚开始学的时候也踩了不少坑。这篇文章就是把我从“Hello World”到写出一个完整天气界面的全过程记录下来把那些容易绊倒的地方都标出来。二、运行环境要求在写代码之前先把环境搭好。以下是完整的环境清单项目版本要求说明操作系统Windows 10/11 (x86_64) 或 macOS 13推荐 Windows模拟器更稳定DevEco Studio5.0.3 Release 及以上鸿蒙官方 IDE下载地址developer.huawei.comHarmonyOS SDKAPI 12 (5.0.0) 及以上IDE 首次启动会自动提示安装Node.js18.x 或 20.x LTS鸿蒙工具链依赖Ohpm随 DevEco Studio 自带鸿蒙包管理器类似 npm模拟器 / 真机API 12 模拟器 或 HarmonyOS NEXT 手机推荐使用远程模拟器免费2.1 安装 DevEco Studio打开华为开发者官网下载 DevEco Studio 安装包。安装过程很简单——一路 Next 即可。首次启动会进入欢迎界面⚠️ 避坑安装路径不要有中文和空格。SDK 路径默认在C:\Users\你的用户名\AppData\Local\Huawei\Sdk如果你 C 盘空间紧张安装时改到 D 盘。2.2 创建项目打开 DevEco Studio →Create Project→ 选择Empty Ability模板 → 填写Project NameWeatherAppBundle Namecom.example.weatherappCompatible API选择 API 12Compatible DevicePhone创建完成后项目结构如下WeatherApp/ ├── entry/ │ └── src/main/ │ ├── ets/ │ │ ├── entryability/ # UIAbility 入口 │ │ └── pages/ # 页面组件我们主要在这里写 │ └── resources/ # 资源文件图片、字符串等 ├── AppScope/ # 应用全局配置 └── build-profile.json5 # 构建配置核心目录是entry/src/main/ets/pages/后面的代码都写在这里。三、实战写一个天气预报界面3.1 最终效果预览先看看我们要实现的目标——一个完整的天气预报 App 首页从上到下依次是城市信息显示城市名和日期天气图标 温度大号天气图标和主温度天气描述文字描述天气状况详情卡片湿度、风速、气压、能见度7 天预报每日天气列表3.2 先学会三个最核心的概念动手写代码前必须搞懂 ArkUI 的三个核心概念。这是博主文章中反复强调的重点。 Entry Component一切 UI 的起点Entry// 标记这个组件是页面入口Component// 标记这是一个自定义组件struct WeatherPage{build(){// 组件必须实现 build() 方法Column(){Text(Hello Weather)}}}Entry一个页面只能有一个它处理页面生命周期onPageShow、onPageHideComponent可以有很多个用于拆分复用 UI 片段build()必须实现框架从这里构建 UI 树 StateUI 自动更新的秘密Componentstruct Counter{Statecount:number0;// State 让变量变成响应式build(){Column(){Text(计数:${this.count})// 用 this. 访问Button(点击 1).onClick((){this.count;// 改值 → UI 自动刷新})}}}核心机制State变量改变时框架自动重新执行build()只更新变化的部分。你不需要像传统 Android 那样手动调用setText()或notifyDataSetChanged()。 Column Row布局两兄弟组件排列方向主轴对齐属性交叉轴对齐属性Column()垂直从上到下justifyContent(FlexAlign.*)alignItems(HorizontalAlign.*)Row()水平从左到右justifyContent(FlexAlign.*)alignItems(VerticalAlign.*)Column(){Row(){Text(左)Text(中)Text(右)}.width(100%).justifyContent(FlexAlign.SpaceBetween)}.width(100%).height(100%).justifyContent(FlexAlign.Center) 最佳实践Column 套 Row 是最常用的布局模式大部分的界面都可以用它俩拼出来。3.3 第一步定义数据模型在pages/目录下创建WeatherData.ets定义天气数据的类型// WeatherData.etsexportinterfaceWeatherData{city:string;// 城市名temperature:number;// 当前温度condition:string;// 天气状况描述humidity:number;// 湿度百分比windSpeed:number;// 风速 km/hicon:string;// 天气图标 emojihigh:number;// 最高温度low:number;// 最低温度}exportinterfaceDailyForecast{day:string;// 星期几icon:string;// 天气图标high:number;// 最高温low:number;// 最低温condition:string;// 天气状况}3.4 第二步编写主界面 Index.ets这是核心文件完整代码如下。建议逐行阅读每个注解都很重要。EntryComponentstruct WeatherPage{// 状态变量 Statecity:string北京Statetemperature:string28°CStatedescription:string晴朗Statehumidity:string60%StatewindSpeed:string12 km/hStatepressure:string1013 hPaStatevisibility:string10 kmStateweatherIcon:string\u2600\uFE0F// ☀️StateisLoading:booleanfalse// 7天预报数据Stateforecast:DailyForecast[][{day:今天,icon:☀️,high:28,low:18,condition:晴},{day:周六,icon:⛅,high:26,low:19,condition:多云},{day:周日,icon:☁️,high:23,low:17,condition:阴},{day:周一,icon:️,high:21,low:16,condition:小雨},{day:周二,icon:☀️,high:25,low:18,condition:晴},{day:周三,icon:⛅,high:27,low:20,condition:多云},{day:周四,icon:☀️,high:29,low:19,condition:晴},]// build 方法构建 UI build(){Column(){// ─── ① 城市和日期 ───Text(this.city).fontSize(22).fontColor(Color.White).fontWeight(FontWeight.Bold).margin({top:60})Text(2025年5月30日 星期五).fontSize(13).fontColor(rgba(255,255,255,0.7)).margin({top:6})// ─── ② 天气图标 ───Text(this.weatherIcon).fontSize(80).margin({top:30})// ─── ③ 温度显示 ───Text(this.temperature).fontSize(64).fontColor(Color.White).fontWeight(FontWeight.Bold)Text(${this.description}· 体感温度 30°).fontSize(14).fontColor(rgba(255,255,255,0.75)).margin({top:4})// ─── ④ 详情卡片湿度/风速/气压/能见度 ───Row(){WeatherDetailItem(label: 湿度,value:this.humidity)VerticalDivider()WeatherDetailItem(label:️ 风速,value:this.windSpeed)}.width(90%).padding(20).margin({top:24}).borderRadius(16).backgroundColor(rgba(255,255,255,0.15))Row(){WeatherDetailItem(label: 气压,value:this.pressure)VerticalDivider()WeatherDetailItem(label:️ 能见度,value:this.visibility)}.width(90%).padding(20).margin({top:12}).borderRadius(16).backgroundColor(rgba(255,255,255,0.15))// ─── ⑤ 7天预报 ───Text( 7天预报).fontSize(16).fontColor(rgba(255,255,255,0.85)).fontWeight(FontWeight.Bold).width(90%).margin({top:24,bottom:10})Column(){ForEach(this.forecast,(item:DailyForecast,index:number){ForecastRow(item)})}.width(90%).padding({top:8,bottom:8}).borderRadius(16).backgroundColor(rgba(255,255,255,0.15))// ─── ⑥ 加载动画下拉刷新效果 ───if(this.isLoading){LoadingProgress().width(32).height(32).color(Color.White).margin({top:16})}}.width(100%).height(100%).justifyContent(FlexAlign.Start).alignItems(HorizontalAlign.Center).linearGradient({direction:GradientDirection.BottomRight,colors:[[#667eea,0],[#764ba2,1]]})}}3.5 第三步编写子组件为了让代码更清晰我们把详情项和预报行拆成独立的子组件。// 天气详情单项Componentstruct WeatherDetailItem{privatelabel:stringprivatevalue:stringbuild(){Column(){Text(this.label).fontSize(13).fontColor(rgba(255,255,255,0.6))Text(this.value).fontSize(18).fontColor(Color.White).fontWeight(FontWeight.Bold).margin({top:6})}.layoutWeight(1)// 均分空间.alignItems(HorizontalAlign.Center)}}// 垂直分隔线Componentstruct VerticalDivider{build(){Divider().vertical(true).height(80%).color(rgba(255,255,255,0.15)).width(1)}}// 单日预报行Componentstruct ForecastRow{privateitem:DailyForecast{day:,icon:,high:0,low:0,condition:}build(){Row(){Text(this.item.day).fontSize(15).fontColor(Color.White).width(60)Text(this.item.icon).fontSize(18).width(50)Text(${this.item.low}° /${this.item.high}°).fontSize(14).fontColor(rgba(255,255,255,0.7)).layoutWeight(1)Text(this.item.condition).fontSize(13).fontColor(rgba(255,255,255,0.45)).width(40)}.width(100%).padding({left:16,right:16,top:10,bottom:10}).alignItems(VerticalAlign.Center)}}3.6 第四步添加网络请求从 API 获取真实天气数据如果你有自己的天气 API Key可以用下面的代码让界面显示真实天气importhttpfromohos.net.http// 在 WeatherPage 组件中添加方法asyncfetchWeatherData(){this.isLoadingtruelethttpRequesthttp.createHttp()leturlhttps://api.openweathermap.org/data/2.5/weather?qBeijingappidYOUR_API_KEYunitsmetriclangzh_cntry{letresponseawaithttpRequest.request(url,{method:http.RequestMethod.GET,expectDataType:http.HttpDataType.OBJECT})if(response.responseCode200){letdataJSON.parse(response.resultasstring)this.temperature${Math.round(data.main.temp)}°Cthis.humidity${data.main.humidity}%this.descriptiondata.weather[0].descriptionthis.windSpeed${data.wind.speed}km/h}}catch(err){console.error(网络请求失败:,JSON.stringify(err))}finally{this.isLoadingfalsehttpRequest.destroy()}}⚠️ 避坑鸿蒙的网络请求必须在entry/src/main/module.json5中添加权限声明requestPermissions:[{name:ohos.permission.INTERNET}]3.7 第五步添加转场动画让天气卡片出现时有平滑动画// 在 build() 里给详情卡片添加 transitionRow(){WeatherDetailItem({label: 湿度,value:this.humidity})VerticalDivider()WeatherDetailItem({label:️ 风速,value:this.windSpeed})}.transition({type:TransitionType.Insert,translate:{x:0,y:30},opacity:0})// 页面显示时自动播放动画.onAppear((){animateTo({duration:500,curve:Curve.EaseOut},(){})})四、避坑指南高频踩坑记录以下是我在实际开发中踩过的坑列出来帮你省流#问题错误写法正确写法1访问状态变量忘加 thisText(count)Text(this.count)2build() 里写了复杂逻辑build() { if(x) { ... } }逻辑放方法里build 只做 UI3图片引用路径不对Image(icon.png)Image($r(app.media.icon))4网络请求没加权限直接调用 http.request先配module.json5权限5State 对象修改不触发刷新obj.key val整个对象重新赋值或用ObjectLink6Column 高度占不满不设置 height.width(100%).height(100%)7模拟器启动慢等 10 秒就关首次启动需要 1-2 分钟耐心等五、最佳实践从一开始就养成好习惯先拆组件再写代码每个独立功能块都拆成ComponentUI 更清晰代码更好复用State 够用就行父子通信用Prop跨组件用Link别一上来就全局状态**颜色走r 资源引用 ∗ ∗ ‘ r 资源引用**r资源引用∗∗‘r(‘app.color.primary’)比硬编码’#667eea’ 更好维护网络请求加 try-catch鸿蒙网络请求失败会抛异常不 catch 就直接闪退字体大小用 fp/sp用fontSize(16)是 vp对 accessibility 不够友好开启预览器DevEco Studio 的 Previewer 比模拟器快得多边写边看布局commit 要小改一个功能提交一次回滚时不会连带六、总结与学习路线到此你从一个完全不懂 ArkUI 的新手完成了第一个完整的鸿蒙原生应用界面。回顾一下这一路学到的知识知识点你学会了什么装饰器Entry / Component / State布局Column / Row / justifyContent / alignItems组件Text / Divider / LoadingProgress / ForEach状态管理State 响应式驱动 UI 自动刷新子组件拆分Prop 传参组件复用网络请求http.createHttp JSON 解析动画transition animateTo权限配置module.json5 声明权限### 推荐学习资源 - **官方文档**[HarmonyOS 应用开发文档](https://developer.huawei.com/consumer/cn/doc/)必看排版极好 - **API 参考**DevEco Studio 内按 CtrlQ 看悬浮文档 - **开源仓库**GitHub 搜索 harmonyos-weather参考别人的项目结构 - **博主系列**[AHuiHatedebug 的鸿蒙系列](https://blog.csdn.net/AHuiHatedebug/)就是我参考的那位大佬 官方文档HarmonyOS 应用开发文档 - 开发者社区华为开发者论坛 - 欢迎加入开源鸿蒙跨平台社区https://openharmonycrossplatform.csdn.net/ --- ---