Flutter三方库鸿蒙实战:基于http和json_annotation的天气查询App(支持HarmonyOS 6.0+ API 20+)
本文通过一个完整的天气查询项目,演示如何使用Flutter在鸿蒙(HarmonyOS 6.0以上,API Level 20+)平台上进行跨端开发,重点讲解三方库(http网络库、json_serializable序列化库)的集成与使用方法,最终将应用运行在鸿蒙设备上。打开ohos/entry/src/main/ets/entryability/EntryAbility.ets,确保它能正确加载Fl
欢迎加入开源鸿蒙跨平台社区: https://openharmonycrossplatform.csdn.net
Flutter三方库鸿蒙实战:基于http和json_annotation的天气查询App(支持HarmonyOS 6.0+ API 20+)
本文通过一个完整的天气查询项目,演示如何使用Flutter在鸿蒙(HarmonyOS 6.0以上,API Level 20+)平台上进行跨端开发,重点讲解三方库(http网络库、json_serializable序列化库)的集成与使用方法,最终将应用运行在鸿蒙设备上。
目录
环境搭建
创建Flutter鸿蒙项目
配置依赖与三方库
实现网络请求与数据解析
构建用户界面
集成与运行
总结与扩展
- 环境搭建
在开始之前,请确保你已经准备好以下环境(满足鸿蒙6.0+、API 20+的要求):
DevEco Studio(≥5.0.0,支持HarmonyOS 6.0)
Flutter SDK(≥3.22,使用支持OpenHarmony/HarmonyOS的flutter-ohos分支)
HarmonyOS SDK(API Level 20 或更高,对应HarmonyOS 6.0及以上)
Node.js(≥18.0)
1.1 安装Flutter for HarmonyOS
由于官方Flutter尚未直接支持鸿蒙,我们需要使用社区维护的flutter-ohos版本。执行以下命令:
bash
git clone https://gitee.com/openharmony-sig/flutter_flutter.git -b stable flutter-ohos
export PATH=“$PATH:pwd/flutter-ohos/bin”
然后运行flutter doctor,确保OHOS一栏显示“工具链可用”,并且检查到鸿蒙SDK路径。
1.2 配置鸿蒙设备(API 20+)
使用DevEco Studio创建一个模拟器,选择Phone类型,系统镜像要求HarmonyOS 6.0 (API 20+)。
或连接真机(系统版本≥HarmonyOS 6.0),开启USB调试。
- 创建Flutter鸿蒙项目
创建一个新项目,项目类型选择“鸿蒙应用”:
bash
flutter create --platforms ohos weather_app
cd weather_app
此时项目目录下会生成ohos文件夹,这是鸿蒙原生工程入口。
打开ohos/entry/src/main/ets/entryability/EntryAbility.ets,确保它能正确加载Flutter入口(默认已配置)。
注意:由于我们使用API 20+,请检查ohos/build-profile.json5中的compileSdkVersion和compatibleSdkVersion是否≥20。若不满足,手动修改为20或更高。
示例配置(ohos/build-profile.json5):
json
{
“app”: {
“products”: [{
“compileSdkVersion”: 20,
“compatibleSdkVersion”: 20,
…
}]
}
}
3. 配置依赖与三方库
我们将使用以下三方库:
http: 发起网络请求获取天气数据
json_annotation + json_serializable: 自动解析JSON
打开pubspec.yaml,添加:
yaml
dependencies:
flutter:
sdk: flutter
http: ^1.2.0
json_annotation: ^4.9.0
dev_dependencies:
build_runner: ^2.4.9
json_serializable: ^6.8.0
运行flutter pub get安装依赖。
- 实现网络请求与数据解析
4.1 设计数据模型
我们以和风天气的公开API为例(需申请免费API Key)。新建lib/models/weather.dart:
dart
// 引入json注解库
import ‘package:json_annotation/json_annotation.dart’;
// 这一行是自动生成代码的关联指令,必须写
part ‘weather.g.dart’;
// 天气主模型
@JsonSerializable()
class Weather {
final String city; // 城市名
final String temperature; // 温度(摄氏度)
final String condition; // 天气状况描述
Weather({
required this.city,
required this.temperature,
required this.condition,
});
// 从JSON生成对象
factory Weather.fromJson(Map<String, dynamic> json) => _$WeatherFromJson(json);
// 对象转JSON(可选)
Map<String, dynamic> toJson() => _$WeatherToJson(this);
}
然后运行命令生成解析代码:
bash
flutter pub run build_runner build
执行后会生成weather.g.dart,其中包含了_KaTeX parse error: Expected group after '_' at position 17: …eatherFromJson和_̲WeatherToJson的具体实现。
4.2 编写网络请求服务
创建lib/services/weather_service.dart:
dart
import ‘package:http/http.dart’ as http;
import ‘dart:convert’;
import ‘…/models/weather.dart’;
class WeatherService {
// 请替换成你的和风天气API Key
static const String apiKey = “YOUR_API_KEY”;
static const String baseUrl = “https://devapi.qweather.com/v7/weather/now”;
// 根据城市名获取实时天气
Future fetchWeather(String city) async {
// 实际和风天气需要先获取LocationID,为简化,此处使用mock或直接请求demo接口
// 注意:以下URL仅为示例,实际需要注册获取key并替换为真实接口
final url = Uri.parse(“baseUrl?location=baseUrl?location=baseUrl?location=city&key=$apiKey”);
try {
final response = await http.get(url);
if (response.statusCode == 200) {
final Map<String, dynamic> data = json.decode(response.body);
// 根据实际返回结构解析(这里简化处理)
final now = data['now'];
return Weather(
city: city,
temperature: now['temp'].toString(),
condition: now['text'],
);
} else {
throw Exception("请求失败:${response.statusCode}");
}
} catch (e) {
// 为演示效果,返回模拟数据(避免因网络或key问题阻塞流程)
return Weather(
city: city,
temperature: "22",
condition: "晴",
);
}
}
}
说明:真实开发时请替换API Key并正确解析。上述代码含异常回退模拟数据,方便新手快速体验。
- 构建用户界面
创建lib/main.dart,完成完整的UI交互:
dart
import ‘package:flutter/material.dart’;
import ‘services/weather_service.dart’;
import ‘models/weather.dart’;
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: ‘鸿蒙天气’,
theme: ThemeData(primarySwatch: Colors.blue),
home: const WeatherPage(),
);
}
}
class WeatherPage extends StatefulWidget {
const WeatherPage({super.key});
@override
State createState() => _WeatherPageState();
}
class _WeatherPageState extends State {
final TextEditingController _cityController = TextEditingController();
Weather? _weather;
bool _loading = false;
String _error = ‘’;
final WeatherService _weatherService = WeatherService();
// 查询天气方法
Future _queryWeather() async {
final city = _cityController.text.trim();
if (city.isEmpty) {
setState(() {
_error = ‘请输入城市名’;
});
return;
}
setState(() {
_loading = true;
_error = '';
_weather = null;
});
try {
final weather = await _weatherService.fetchWeather(city);
setState(() {
_weather = weather;
_loading = false;
});
} catch (e) {
setState(() {
_error = e.toString();
_loading = false;
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text(‘Flutter三方库鸿蒙天气查询’),
backgroundColor: Colors.blueAccent,
),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
children: [
// 输入框和按钮
Row(
children: [
Expanded(
child: TextField(
controller: _cityController,
decoration: const InputDecoration(
hintText: ‘请输入城市名,例如:Beijing’,
border: OutlineInputBorder(),
),
),
),
const SizedBox(width: 10),
ElevatedButton(
onPressed: _queryWeather,
child: const Text(‘查询’),
),
],
),
const SizedBox(height: 20),
// 加载指示器
if (_loading) const CircularProgressIndicator(),
// 错误信息
if (_error.isNotEmpty)
Text(_error, style: const TextStyle(color: Colors.red)),
// 天气数据显示
if (_weather != null) …[
const SizedBox(height: 20),
Card(
elevation: 4,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
Text(
_weather!.city,
style: const TextStyle(fontSize: 28, fontWeight: FontWeight.bold),
),
const SizedBox(height: 10),
Text(
‘${_weather!.temperature}°C’,
style: const TextStyle(fontSize: 48),
),
const SizedBox(height: 10),
Text(
_weather!.condition,
style: const TextStyle(fontSize: 20),
),
],
),
),
),
],
],
),
),
);
}
}
代码说明
WeatherService封装了网络请求逻辑,使用http库发起GET请求。
json_annotation自动生成解析代码,使模型层简洁。
UI使用StatefulWidget管理加载状态和数据显示,提供良好的用户体验。
- 集成与运行
6.1 配置鸿蒙应用权限
由于需要访问网络,必须在鸿蒙工程中申请权限。打开ohos/entry/src/main/module.json5,在requestPermissions中添加:
json
{
“name”: “ohos.permission.INTERNET”
}
6.2 确保API版本符合要求
检查ohos/entry/build-profile.json5中的compileSdkVersion和compatibleSdkVersion均设置为20或更高。例如:
json
{
“apiType”: “stageMode”,
“buildOption”: {},
“targets”: [
{
“name”: “default”,
“runtimeOS”: “HarmonyOS”,
“config”: {
“compileSdkVersion”: 20,
“compatibleSdkVersion”: 20
}
}
]
}
6.3 运行应用
确保鸿蒙设备或模拟器(系统≥HarmonyOS 6.0)已启动,执行:
bash
flutter run -d ohos
第一次运行时会编译鸿蒙原生部分,稍等片刻。成功后,你将看到如下界面:
输入城市名(如“Shanghai”)
点击“查询”,显示天气数据(模拟或真实数据)
6.4 真机调试提示
如果使用真机,请确保鸿蒙系统版本≥HarmonyOS 6.0。
若遇到签名问题,在DevEco Studio中完成自动签名(File → Project Structure → Signing)。
- 总结与扩展
通过本文的实践,你完成了以下内容:
环境搭建:配置支持HarmonyOS 6.0+ API 20+的Flutter开发环境。
三方库使用:集成了http和json_annotation库,实现了网络请求和数据自动解析。
完整项目:构建了一个具备输入查询、网络请求、结果显示的天气应用,并成功运行在鸿蒙设备上。
扩展建议
将API替换为真实服务(和风天气、心知天气等),注意处理异步错误和加载状态。
增加本地存储(使用shared_preferences库缓存最近查询的城市)。
使用provider或riverpod进行状态管理,优化代码结构。
适配鸿蒙的分布式能力,例如跨设备流转天气信息。
Flutter跨端开发在鸿蒙平台上的潜力巨大,社区的三方库生态正逐步完善。希望本文能帮助你快速上手鸿蒙跨端开发,享受一次编写、多端运行的乐趣。
附录:常见问题
Q: 运行flutter run -d ohos报错“No connected devices”?
A: 检查DevEco Studio是否启动了模拟器(API 20+),或执行flutter devices查看设备列表。
Q: 鸿蒙编译失败,提示“ohpm”找不到?
A: 需要安装ohpm,并在DevEco Studio中设置OHPM路径(通常随IDE自带,检查环境变量)。
Q: 网络请求失败?
A: 确认鸿蒙设备已联网,且module.json5中已添加INTERNET权限,同时检查API版本是否满足20+。
Q: json_serializable生成代码时报错?
A: 确保part ‘weather.g.dart’;和注解正确,运行flutter clean后重新生成。
完整示例源码可参考:https://gitee.com/example/weather_ohos_demo(示例链接)
更多推荐



所有评论(0)