
鸿蒙5开发实战:基于ArkUI与网络请求的天气应用开发
随着鸿蒙5的发布,ArkCompiler和ArkUI等开发工具进一步成熟,为开发者提供了更强大的能力。本文将介绍如何使用鸿蒙5的开发工具和ArkCompiler来开发一个功能完整的天气应用,涵盖ArkUI布局设计和网络请求的综合实践。
项目概述
我们将开发一个简单的天气应用,主要功能包括:
显示当前城市的天气信息
支持城市搜索
展示未来几天的天气预报
使用网络API获取实时天气数据
开发环境准备
确保你已经安装了以下工具:
DevEco Studio 5.0或更高版本
鸿蒙5 SDK
ArkCompiler工具链
项目结构
WeatherApp/
├── entry/
│ ├── src/
│ │ ├── main/
│ │ │ ├── ets/
│ │ │ │ ├── components/ # 自定义组件
│ │ │ │ ├── model/ # 数据模型
│ │ │ │ ├── pages/ # 页面
│ │ │ │ ├── utils/ # 工具类
│ │ │ │ └── app.ets # 应用入口
│ │ │ └── resources/ # 资源文件
数据模型定义
首先,我们定义天气数据的模型:
// model/WeatherData.ets
export interface WeatherInfo {
city: string;
temperature: number;
weather: string;
humidity: number;
windSpeed: number;
airQuality: string;
icon: string;
}
export interface Forecast {
date: string;
dayTemp: number;
nightTemp: number;
weather: string;
icon: string;
}
export interface WeatherResponse {
current: WeatherInfo;
forecast: Forecast[];
}
网络请求封装
使用鸿蒙的网络模块封装天气API请求:
// utils/http.ets
import http from ‘@ohos.net.http’;
import { WeatherResponse } from ‘…/model/WeatherData’;
const BASE_URL = ‘https://api.weather.example.com’;
export class WeatherService {
private httpRequest = http.createHttp();
async getWeather(city: string): Promise<WeatherResponse> {
return new Promise((resolve, reject) => {
this.httpRequest.request(
${BASE_URL}/weather?city=${encodeURIComponent(city)}
,
{
method: ‘GET’,
header: {
‘Content-Type’: ‘application/json’
}
},
(err, data) => {
if (err) {
reject(err);
return;
}
try {
const result = JSON.parse(data.result as string) as WeatherResponse;
resolve(result);
} catch (e) {
reject(e);
}
}
);
});
}
destroy() {
this.httpRequest.destroy();
}
}
主页面实现
下面是主页面代码,展示当前天气和预报:
// pages/HomePage.ets
import { WeatherInfo, Forecast, WeatherResponse } from ‘…/model/WeatherData’;
import { WeatherService } from ‘…/utils/http’;
@Entry
@Component
struct HomePage {
private weatherService = new WeatherService();
@State currentWeather: WeatherInfo | null = null;
@State forecastList: Forecast[] = [];
@State searchCity: string = ‘北京’;
@State isLoading: boolean = false;
@State errorMessage: string = ‘’;
aboutToAppear() {
this.loadWeather();
}
loadWeather() {
this.isLoading = true;
this.errorMessage = ‘’;
this.weatherService.getWeather(this.searchCity)
.then((response) => {
this.currentWeather = response.current;
this.forecastList = response.forecast;
})
.catch((err) => {
this.errorMessage = '获取天气数据失败: ' + err.message;
console.error(err);
})
.finally(() => {
this.isLoading = false;
});
}
build() {
Column() {
// 搜索栏
Row() {
TextInput({ placeholder: ‘输入城市名称’, text: this.searchCity })
.onChange((value: string) => {
this.searchCity = value;
})
.layoutWeight(1)
.height(40)
.margin(10)
Button('搜索')
.onClick(() => {
this.loadWeather();
})
.height(40)
.margin(10)
}
.width('100%')
.padding(10)
// 加载状态和错误提示
if (this.isLoading) {
LoadingProgress()
.width(50)
.height(50)
}
if (this.errorMessage) {
Text(this.errorMessage)
.fontSize(16)
.fontColor(Color.Red)
.margin(10)
}
// 当前天气信息
if (this.currentWeather) {
CurrentWeatherView({ weather: this.currentWeather })
}
// 天气预报列表
if (this.forecastList.length > 0) {
Text('未来几天天气预报')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.margin({ top: 20, bottom: 10 })
List({ space: 10 }) {
ForEach(this.forecastList, (item: Forecast) => {
ListItem() {
ForecastItem({ forecast: item })
}
})
}
.layoutWeight(1)
.width('100%')
}
}
.width('100%')
.height('100%')
.padding(10)
}
aboutToDisappear() {
this.weatherService.destroy();
}
}
自定义组件
当前天气组件
// components/CurrentWeatherView.ets
import { WeatherInfo } from ‘…/model/WeatherData’;
@Component
export struct CurrentWeatherView {
private weather: WeatherInfo;
build() {
Column() {
Text(this.weather.city)
.fontSize(24)
.fontWeight(FontWeight.Bold)
Row() {
Image(this.weather.icon)
.width(80)
.height(80)
Column() {
Text(`${this.weather.temperature}°C`)
.fontSize(36)
.fontWeight(FontWeight.Bold)
Text(this.weather.weather)
.fontSize(18)
}
.margin({ left: 10 })
}
.justifyContent(FlexAlign.Center)
.margin({ top: 10, bottom: 10 })
Grid() {
GridItem() {
Column() {
Text('湿度')
.fontSize(14)
Text(`${this.weather.humidity}%`)
.fontSize(16)
.fontWeight(FontWeight.Bold)
}
}
GridItem() {
Column() {
Text('风速')
.fontSize(14)
Text(`${this.weather.windSpeed} km/h`)
.fontSize(16)
.fontWeight(FontWeight.Bold)
}
}
GridItem() {
Column() {
Text('空气质量')
.fontSize(14)
Text(this.weather.airQuality)
.fontSize(16)
.fontWeight(FontWeight.Bold)
}
}
}
.columnsTemplate('1fr 1fr 1fr')
.rowsGap(10)
.columnsGap(10)
.width('100%')
}
.width('100%')
.padding(15)
.borderRadius(10)
.backgroundColor('#f0f0f0')
}
}
天气预报项组件
// components/ForecastItem.ets
import { Forecast } from ‘…/model/WeatherData’;
@Component
export struct ForecastItem {
private forecast: Forecast;
build() {
Row() {
Column() {
Text(this.forecast.date)
.fontSize(16)
.fontWeight(FontWeight.Bold)
Text(`${this.forecast.dayTemp}°C / ${this.forecast.nightTemp}°C`)
.fontSize(14)
}
.layoutWeight(1)
Row() {
Image(this.forecast.icon)
.width(40)
.height(40)
Text(this.forecast.weather)
.fontSize(14)
.margin({ left: 5 })
}
}
.width('100%')
.padding(10)
.borderRadius(5)
.backgroundColor('#f8f8f8')
}
}
ArkCompiler优化
鸿蒙5的ArkCompiler在性能上有显著提升,我们可以通过以下方式进一步优化:
组件复用:确保自定义组件尽可能复用
状态管理:合理使用@State, @Prop, @Link等装饰器
列表优化:对于长列表使用LazyForEach代替ForEach
图片缓存:实现图片缓存机制减少网络请求
项目配置
在module.json5中添加网络权限:
{
“module”: {
“requestPermissions”: [
{
“name”: “ohos.permission.INTERNET”
}
]
}
}
总结
通过这个天气应用的开发实践,我们学习了:
如何使用ArkUI构建复杂的用户界面
如何发起网络请求并处理响应数据
如何组织鸿蒙应用的项目结构
如何创建可复用的自定义组件
鸿蒙5中ArkCompiler的性能优化技巧
鸿蒙5的ArkCompiler和ArkUI框架为开发者提供了强大的工具,使得开发高性能、美观的应用变得更加简单。随着鸿蒙生态的不断发展,这些工具将会变得更加强大和易用。
希望这篇文章能帮助你入门鸿蒙5的应用开发,特别是ArkUI和网络请求的综合使用。你可以在此基础上进一步扩展功能,如添加城市收藏、天气预警通知等。
