跨平台开发与HarmonyOS生态融合的趋势下,利用Flutter快速构建UI、DevEco Studio适配HarmonyOS设备的开发模式,能有效提升应用开发效率。本文将以"简易天气查询工具"为案例,详细讲解Flutter与DevEco Studio结合开发的全流程,涵盖环境复用、项目搭建、网络请求、数据展示及HarmonyOS适配等核心环节,适合具备基础Flutter和HarmonyOS开发基础的开发者学习参考。
Flutter+DevEco Studio实战:简易天气查询工具开发指南大纲
项目背景与目标
- 介绍Flutter框架的跨平台优势
- DevEco Studio作为HarmonyOS开发工具的特点
- 简易天气查询工具的功能需求和适用场景
开发环境配置
- 安装Flutter SDK并配置环境变量
- 安装DevEco Studio及HarmonyOS开发插件
- 检查Flutter与DevEco Studio的兼容性
项目初始化
- 使用Flutter CLI创建新项目
- 在DevEco Studio中导入Flutter项目
- 配置项目依赖(如http、provider等常用库)
界面设计与布局
- 使用Flutter Widget构建主页面框架
- 实现城市搜索输入框和查询按钮
- 设计天气信息展示区域(温度、湿度、天气图标等)
数据获取与处理
- 调用第三方天气API(如和风天气)
- 解析返回的JSON数据并转换为Dart对象
- 使用Provider或Bloc进行状态管理
功能逻辑实现
- 实现城市搜索功能与API请求绑定
- 处理网络请求异常和加载状态
- 动态更新UI以反映天气数据变化
跨平台适配与优化
- 检查HarmonyOS平台上的兼容性问题
- 优化布局在不同设备上的显示效果
- 测试应用在Android/iOS/HarmonyOS上的运行情况
调试与发布
- 使用DevEco Studio的调试工具排查问题
- 生成HarmonyOS应用发布包(.hap文件)
- 上架到华为应用市场的简要流程说明
总结与扩展
- 回顾关键技术点和解决方案
- 提出进一步功能扩展建议(如多语言支持、天气预警等)
- 推荐学习资源与社区支持

一、项目概述与环境复用
1.1 项目核心功能
本次开发的简易天气查询工具,实现3个核心功能:输入城市名称查询天气、展示实时温度/天气状况/风力等信息、处理网络异常与空输入提示。项目采用Flutter构建跨平台UI,通过第三方天气API获取数据,最终基于DevEco Studio适配HarmonyOS设备运行。
1.2 环境复用说明
本文复用前文"待办事项列表"项目的开发环境,无需重复配置。核心环境要求如下表所示,若环境未配置完成,可参考前文"前置知识与环境准备"章节完成配置:
| 工具名称 | 最低版本要求 | 核心作用 |
|---|---|---|
| DevEco Studio | 4.1.0.600 | HarmonyOS设备适配、项目编译运行 |
| Flutter SDK | 3.16.0 | 构建统一风格的天气查询UI界面 |
| Dart SDK | 3.2.0 | 编写Flutter业务逻辑与网络请求代码 |
| HarmonyOS SDK | API Version 9 | 保障应用在HarmonyOS手机/模拟器正常运行 |
二、项目初始化与依赖配置
2.1 新建Flutter项目
-
打开DevEco Studio,选择
File > New > New Flutter Project,选择"Flutter Application",点击"Next"。 -
配置项目信息:Project Name设为"flutter_harmony_weather",Package Name遵循HarmonyOS规范(如"com.example.flutterharmonyweather"),选择项目保存路径后点击"Finish"。
2.2 核心依赖配置
项目需引入网络请求、JSON解析相关依赖,修改pubspec.yaml文件,在dependencies节点下添加以下配置:
dependencies:
flutter:
sdk: flutter
http: ^0.13.5 # 用于发送网络请求获取天气数据
json_annotation: ^4.8.1 # 用于JSON数据模型序列化/反序列化
flutter_harmony: ^0.1.0 # 保障Flutter与HarmonyOS兼容性
dev_dependencies:
flutter_test:
sdk: flutter
build_runner: ^2.4.4 # 生成JSON解析相关代码
json_serializable: ^6.7.0 # 配合json_annotation实现JSON解析
配置完成后,在终端执行flutter pub get拉取依赖,确保无依赖冲突。
三、核心功能实现
3.1 天气数据模型定义
选择"聚合数据"免费天气API(需提前注册获取API密钥),API返回数据包含城市、温度、天气状况等信息。在lib/models/weather_model.dart中定义数据模型,代码如下:
import 'package:json_annotation/json_annotation.dart';
// 生成的解析代码会在该路径下,需先执行build_runner命令
part 'weather_model.g.dart';
@JsonSerializable()
class WeatherResponse {
final int error_code; // 错误码,0表示成功
final String reason; // 提示信息
final WeatherResult result;
WeatherResponse({
required this.error_code,
required this.reason,
required this.result,
});
// 从JSON转换为模型对象
factory WeatherResponse.fromJson(Map<String, dynamic> json) = _$WeatherResponseFromJson;
// 从模型对象转换为JSON
Map<String, dynamic> toJson() = _$WeatherResponseToJson;
}
@JsonSerializable()
class WeatherResult {
final String city; // 城市名称
final RealTimeWeather realtime; // 实时天气信息
WeatherResult({required this.city, required this.realtime});
factory WeatherResult.fromJson(Map<String, dynamic> json) = _$WeatherResultFromJson;
Map<String, dynamic> toJson() = _$WeatherResultToJson;
}
@JsonSerializable()
class RealTimeWeather {
final String info; // 天气状况(如晴、阴)
final String temperature; // 实时温度
final String humidity; // 湿度
final String direct; // 风向
final String power; // 风力
RealTimeWeather({
required this.info,
required this.temperature,
required this.humidity,
required this.direct,
required this.power,
});
factory RealTimeWeather.fromJson(Map<String, dynamic> json) = _$RealTimeWeatherFromJson;
Map<String, dynamic> toJson() = _$RealTimeWeatherToJson;
}
执行flutter pub run build_runner build生成JSON解析代码(即weather_model.g.dart),若后续修改模型,需重新执行该命令。
3.2 网络请求工具类实现
在lib/utils/network_utils.dart中封装网络请求工具类,统一处理请求发送与异常捕获:
import 'dart:convert';
import 'package:http/http.dart' as http;
import '../models/weather_model.dart';
class NetworkUtils {
// 聚合数据天气API地址(替换为自己的API密钥)
static const String _weatherApiUrl = "http://v.juhe.cn/weather/index?format=2&key=YOUR_API_KEY&cityname=";
// 根据城市名称查询天气
static Future<WeatherResponse?> fetchWeather(String cityName) async {
try {
final response = await http.get(Uri.parse(_weatherApiUrl + cityName));
if (response.statusCode == 200) {
// 解析JSON数据为模型对象
return WeatherResponse.fromJson(json.decode(response.body));
} else {
print("网络请求失败,状态码:${response.statusCode}");
return null;
}
} catch (e) {
print("网络请求异常:$e");
return null;
}
}
}
注意:将YOUR_API_KEY替换为自己在聚合数据平台获取的天气API密钥。
3.3 主页面UI与业务逻辑实现
在lib/main.dart中实现天气查询主页面,包含城市输入框、查询按钮、天气信息展示区域,以及加载状态与异常提示:
import 'package:flutter/material.dart';
import 'models/weather_model.dart';
import 'utils/network_utils.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter-Harmony天气查询',
theme: ThemeData(primarySwatch: Colors.blue),
home: const WeatherQueryPage(),
);
}
}
class WeatherQueryPage extends StatefulWidget {
const WeatherQueryPage({super.key});
@override
State<WeatherQueryPage> createState() => _WeatherQueryPageState();
}
class _WeatherQueryPageState extends State<WeatherQueryPage> {
final TextEditingController _cityController = TextEditingController();
WeatherResult? _weatherResult; // 存储查询到的天气结果
bool _isLoading = false; // 加载状态标识
String _errorMsg = ""; // 错误提示信息
// 查询天气方法
void _queryWeather() {
final cityName = _cityController.text.trim();
if (cityName.isEmpty) {
setState(() {
_errorMsg = "请输入城市名称";
_weatherResult = null;
});
return;
}
setState(() {
_isLoading = true;
_errorMsg = "";
});
// 调用网络工具类查询天气
NetworkUtils.fetchWeather(cityName).then((response) {
setState(() {
_isLoading = false;
if (response != null && response.error_code == 0) {
_weatherResult = response.result;
} else {
_errorMsg = response?.reason ?? "查询失败,请重试";
_weatherResult = null;
}
});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('简易天气查询')),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
// 城市输入框与查询按钮
Row(
children: [
Expanded(
child: TextField(
controller: _cityController,
decoration: const InputDecoration(
hintText: '请输入城市名称(如北京)',
border: OutlineInputBorder(),
),
),
),
const SizedBox(width: 10),
ElevatedButton(
onPressed: _isLoading ? null : _queryWeather,
child: _isLoading
? const CircularProgressIndicator(color: Colors.white, strokeWidth: 2)
: const Text('查询'),
),
],
),
const SizedBox(height: 20),
// 错误提示
if (_errorMsg.isNotEmpty)
Text(
_errorMsg,
style: const TextStyle(color: Colors.red, fontSize: 14),
),
// 天气信息展示区域
if (_weatherResult != null)
Expanded(
child: Card(
elevation: 5,
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'城市:${_weatherResult!.city}',
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
const SizedBox(height: 20),
Text('天气状况:${_weatherResult!.realtime.info}', style: const TextStyle(fontSize: 16)),
const SizedBox(height: 10),
Text('实时温度:${_weatherResult!.realtime.temperature}℃', style: const TextStyle(fontSize: 16)),
const SizedBox(height: 10),
Text('湿度:${_weatherResult!.realtime.humidity}%', style: const TextStyle(fontSize: 16)),
const SizedBox(height: 10),
Text('风向:${_weatherResult!.realtime.direct}', style: const TextStyle(fontSize: 16)),
const SizedBox(height: 10),
Text('风力:${_weatherResult!.realtime.power}级', style: const TextStyle(fontSize: 16)),
],
),
),
),
),
],
),
),
);
}
}
3.4 HarmonyOS适配配置
修改harmony/src/main/config.json文件,配置应用基本信息与设备支持类型,确保适配HarmonyOS设备:
{
"app": {
"bundleName": "com.example.flutterharmonyweather",
"vendor": "example",
"version": {
"code": 1000000,
"name": "1.0.0"
}
},
"module": {
"package": "com.example.flutterharmonyweather",
"name": ".MainApplication",
"mainAbility": "com.example.flutterharmonyweather.MainAbility",
"deviceType": ["phone"], // 支持手机设备
"distro": {
"deliveryWithInstall": true,
"moduleName": "flutter_harmony_weather",
"moduleType": "entry",
"installationFree": false
},
"abilities": [
{
"name": "com.example.flutterharmonyweather.MainAbility",
"label": "天气查询工具",
"icon": "$media:icon",
"description": "$string:mainability_description",
"skills": [
{
"entities": ["entity.system.home"],
"actions": ["action.system.home"]
}
]
}
]
}
}
四、项目运行与调试
4.1 运行步骤
-
启动HarmonyOS模拟器:打开DevEco Studio的"Device Manager",选择Phone API 9模拟器并启动。
-
确认依赖已安装:终端执行
flutter pub get,确保所有依赖加载完成。 -
选择运行设备:在DevEco Studio工具栏选择已启动的HarmonyOS模拟器。
-
启动项目:点击工具栏"运行"按钮(或快捷键Shift+F10),等待项目编译部署完成。
4.2 关键调试点
-
API密钥问题:若出现"查询失败",优先检查API密钥是否正确、是否过期,可直接在浏览器访问API地址验证密钥有效性。
-
网络权限 :若出现网络请求失败,需确认HarmonyOS模拟器已连接网络,同时检查应用是否开启网络权限(DevEco Studio中可通过
config.json添加网络权限配置)。 -
JSON解析错误 :若出现解析异常,检查API返回数据格式是否与模型定义一致,可通过
print(response.body)打印返回数据进行排查。
五、项目扩展方向
本项目为基础版本,可在此基础上扩展以下功能提升应用实用性,具体扩展方向、实现方式及核心价值如下表所示:
| 扩展功能 | 实现方式 | 核心价值 |
|---|---|---|
| 添加城市选择器 | 集成flutter_picker等第三方选择器插件,预设热门城市列表,替换原有输入框 | 降低用户输入成本,避免因城市名称输入错误导致的查询失败 |
| 新增未来几天天气预报 | 调用聚合数据天气API的多日预报接口,扩展WeatherModel数据模型,新增列表展示多日数据 | 丰富天气信息维度,满足用户对未来天气的查询需求 |
| 数据持久化 | 结合HarmonyOS的Preferences组件,封装数据存储工具类,保存历史查询记录 | 提升用户体验,用户下次打开应用可快速查看历史查询过的城市天气 |
| 主题切换 | 使用Flutter的Provider状态管理工具,定义浅色/深色主题配置,添加主题切换按钮控制状态 | 适配不同使用场景(如夜间使用),提升应用视觉舒适度 |
六、总结
本文通过"简易天气查询工具"项目,进一步演示了Flutter与DevEco Studio结合开发的实战流程,重点讲解了网络请求、JSON解析、HarmonyOS应用配置等核心知识点。相比上一个待办事项项目,本项目更贴近实际应用场景,涉及第三方API调用与数据处理,能帮助开发者更好地掌握跨平台技术与HarmonyOS生态的融合技巧。
开发过程中,需重点关注环境兼容性、API调用规范性及HarmonyOS配置正确性。若遇到问题,可结合IDE日志、官方文档及社区资源排查解决,逐步提升跨平台+HarmonyOS开发的实战能力。
欢迎大家加入[开源鸿蒙跨平台开发者社区](https://openharmonycrossplatform.csdn.net),一起共建开源鸿蒙跨平台生态。