Flutter 跨平台实战:鸿蒙 6.0 (API20) 集成三方库开发天气查询应用
本项目完整展示了Flutter 结合三方库开发鸿蒙 6.0 应用的全流程,贴合实际开发场景。借助 Flutter 跨平台特性,一套代码可同时运行在 Android、iOS、鸿蒙设备上,大幅降低鸿蒙应用开发成本。
Flutter 跨平台实战:鸿蒙 6.0 (API20) 集成三方库开发天气查询应用
前言
对于鸿蒙开发者入门 Flutter 跨平台开发,借助成熟三方库可以快速实现复杂功能。本文以跨平台天气查询应用为案例,在鸿蒙 6.0 (API20) 环境下,集成网络请求、JSON 解析、位置获取、UI 美化三方库,完成可落地的跨端应用。
一、环境配置要求
-
Flutter 3.16 及以上版本
-
DevEco Studio 搭载鸿蒙 6.0 (API20) 模拟器 / 真机
-
开启网络权限、定位权限
-
代码编辑器:Android Studio / VS Code
二、项目创建与鸿蒙适配配置
1. 创建 Flutter 项目
flutter create flutter\_harmony\_weather
cd flutter\_harmony\_weather
2. 鸿蒙 6.0 适配配置
修改android/app/build.gradle,匹配鸿蒙底层适配要求
android {
  compileSdkVersion 33
  defaultConfig {
  applicationId "com.example.flutter\_harmony\_weather"
  minSdkVersion 21
  targetSdkVersion 33
  versionCode 1
  versionName "1.0"
  }
}
3. 权限配置
打开android/app/src/main/AndroidManifest.xml,添加权限
\<!-- 网络权限 -->
\<uses-permission android:name="android.permission.INTERNET"/>
\<!-- 定位权限 -->
\<uses-permission android:name="android.permission.ACCESS\_FINE\_LOCATION"/>
\<uses-permission android:name="android.permission.ACCESS\_COARSE\_LOCATION"/>
三、引入兼容鸿蒙的三方库
本次选用在鸿蒙 6.0 上运行稳定的常用库,在pubspec.yaml中添加依赖
dependencies:
  flutter:
  sdk: flutter
  \# 网络请求三方库
  dio: ^5.4.0
  \# 定位获取三方库
  geolocator: ^10.1.0
  \# 加载状态提示库
  flutter\_easyloading: ^3.0.5
  \# 图标美化库
  font\_awesome\_flutter: ^10.6.0
执行依赖安装命令
flutter pub get
四、项目结构规划
lib/
├── main.dart # 应用入口
├── models/weather\_model.dart # 天气数据模型
├── utils/api\_util.dart # 网络请求工具
├── pages/weather\_page.dart # 主页面
五、代码实现
1. 天气数据模型:models/weather_model.dart
解析接口返回的 JSON 数据,结构化存储天气信息
/// 天气数据模型
class WeatherModel {
  final String city; // 城市
  final String temp; // 温度
  final String weather; // 天气状况
  final String wind; // 风力
  final String humidity; // 湿度
  WeatherModel({
  required this.city,
  required this.temp,
  required this.weather,
  required this.wind,
  required this.humidity,
  });
  // 解析JSON数据,此处适配简易天气接口
  factory WeatherModel.fromJson(Map\<String, dynamic> json) {
  return WeatherModel(
  city: json\['city'] ?? '未知城市',
  temp: json\['temp'] ?? 'N/A',
  weather: json\['weather'] ?? '未知天气',
  wind: json\['wind'] ?? 'N/A',
  humidity: json\['humidity'] ?? 'N/A',
  );
  }
}
2. 网络请求工具:utils/api_util.dart
基于 dio 三方库实现网络请求,封装获取天气方法
import 'package:dio/dio.dart';
import '../models/weather\_model.dart';
class ApiUtil {
  final Dio \_dio = Dio();
  /// 获取指定城市天气
  Future\<WeatherModel> getWeather(String city) async {
  try {
  // 免费天气接口,可自行替换为正规天气API
  final response = await \_dio.get(
  'https://api.example.com/weather',
  queryParameters: {'city': city},
  );
  return WeatherModel.fromJson(response.data);
  } catch (e) {
  rethrow;
  }
  }
}
3. 主页面实现:pages/weather_page.dart
集成定位、网络请求、加载提示三方库,实现核心交互
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
import 'package:flutter\_easyloading/flutter\_easyloading.dart';
import 'package:font\_awesome\_flutter/font\_awesome\_flutter.dart';
import '../utils/api\_util.dart';
import '../models/weather\_model.dart';
class WeatherPage extends StatefulWidget {
  const WeatherPage({super.key});
  @override
  State\<WeatherPage> createState() => \_WeatherPageState();
}
class \_WeatherPageState extends State\<WeatherPage> {
  final ApiUtil \_apiUtil = ApiUtil();
  WeatherModel? \_weatherModel;
  final TextEditingController \_cityController = TextEditingController();
  @override
  void initState() {
  super.initState();
  // 初始化加载提示组件
  EasyLoading.init();
  }
  /// 获取定位权限并定位当前城市
  Future\<void> getLocationWeather() async {
  EasyLoading.show(status: '获取定位中...');
  // 检查定位权限
  bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
  if (!serviceEnabled) {
  EasyLoading.showError('定位服务未开启');
  return;
  }
  LocationPermission permission = await Geolocator.checkPermission();
  if (permission == LocationPermission.denied) {
  permission = await Geolocator.requestPermission();
  if (permission == LocationPermission.denied) {
  EasyLoading.showError('定位权限被拒绝');
  return;
  }
  }
  if (permission == LocationPermission.deniedForever) {
  EasyLoading.showError('权限永久拒绝,无法定位');
  return;
  }
  // 获取定位坐标,实际开发可通过经纬度获取城市
  Position position = await Geolocator.getCurrentPosition();
  await getWeatherData('北京');
  }
  /// 获取天气数据
  Future\<void> getWeatherData(String city) async {
  if (city.isEmpty) {
  EasyLoading.showInfo('请输入城市名称');
  return;
  }
  EasyLoading.show(status: '加载天气中...');
  try {
  final data = await \_apiUtil.getWeather(city);
  setState(() {
  \_weatherModel = data;
  });
  EasyLoading.showSuccess('加载成功');
  } catch (e) {
  EasyLoading.showError('获取天气失败:\${e.toString()}');
  }
  }
  @override
  Widget build(BuildContext context) {
  return Scaffold(
  appBar: AppBar(
  title: const Text('Flutter鸿蒙天气查询'),
  centerTitle: true,
  ),
  body: SingleChildScrollView(
  padding: const EdgeInsets.all(20),
  child: Column(
  children: \[
  // 城市输入框
  TextField(
  controller: \_cityController,
  decoration: InputDecoration(
  hintText: '请输入城市名称',
  suffixIcon: IconButton(
  icon: const Icon(Icons.search),
  onPressed: () {
  getWeatherData(\_cityController.text.trim());
  },
  ),
  border: const OutlineInputBorder(),
  ),
  ),
  const SizedBox(height: 15),
  // 定位获取天气按钮
  ElevatedButton.icon(
  onPressed: getLocationWeather,
  icon: const FaIcon(FontAwesomeIcons.locationCrosshairs),
  label: const Text('定位获取当前天气'),
  ),
  const SizedBox(height: 30),
  // 天气信息展示区域
  if (\_weatherModel != null)
  Card(
  elevation: 5,
  shape: RoundedRectangleBorder(
  borderRadius: BorderRadius.circular(15),
  ),
  child: Padding(
  padding: const EdgeInsets.all(25),
  child: Column(
  children: \[
  Text(
  \_weatherModel!.city,
  style: const TextStyle(
  fontSize: 24, fontWeight: FontWeight.bold),
  ),
  const SizedBox(height: 20),
  Text(
  '\${\_weatherModel!.temp}℃',
  style: const TextStyle(fontSize: 40),
  ),
  const SizedBox(height: 10),
  Text(
  \_weatherModel!.weather,
  style: const TextStyle(fontSize: 20),
  ),
  const Divider(height: 30),
  Row(
  mainAxisAlignment: MainAxisAlignment.spaceAround,
  children: \[
  \_weatherItem(
  FontAwesomeIcons.wind,
  '风力',
  \_weatherModel!.wind,
  ),
  \_weatherItem(
  FontAwesomeIcons.droplet,
  '湿度',
  \_weatherModel!.humidity,
  ),
  ],
  ),
  ],
  ),
  ),
  ),
  ],
  ),
  ),
  );
  }
  /// 天气信息子项
  Widget \_weatherItem(IconData icon, String title, String value) {
  return Column(
  children: \[
  FaIcon(icon, size: 25),
  const SizedBox(height: 5),
  Text(title),
  Text(value),
  ],
  );
  }
}
4. 应用入口:main.dart
全局配置加载提示,挂载主页面
import 'package:flutter/material.dart';
import 'package:flutter\_easyloading/flutter\_easyloading.dart';
import 'pages/weather\_page.dart';
void main() {
  runApp(const MyApp());
}
class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
  return MaterialApp(
  title: 'Flutter鸿蒙天气',
  theme: ThemeData(primarySwatch: Colors.blue),
  home: const WeatherPage(),
  // 配置加载提示三方库
  builder: EasyLoading.init(),
  debugShowCheckedModeBanner: false,
  );
  }
}
六、鸿蒙 6.0 (API20) 运行步骤
-
启动 DevEco Studio 中鸿蒙 6.0 API20 模拟器
-
连接设备后执行运行命令
flutter run
-
授予应用定位、网络权限
-
输入城市或使用定位功能获取天气信息
七、三方库在鸿蒙平台的使用说明
-
dio:网络请求无兼容问题,可正常请求天气接口
-
geolocator:适配鸿蒙定位服务,可成功获取设备位置
-
flutter_easyloading:加载弹窗在鸿蒙设备渲染正常
-
font_awesome_flutter:矢量图标完美展示
八、开发注意事项
-
正式开发需替换为合规商用天气 API,替换接口地址即可
-
鸿蒙设备需手动开启应用权限,否则定位功能无法使用
-
网络请求需处理异常情况,提升应用稳定性
九、总结
本项目完整展示了Flutter 结合三方库开发鸿蒙 6.0 应用的全流程,贴合实际开发场景。借助 Flutter 跨平台特性,一套代码可同时运行在 Android、iOS、鸿蒙设备上,大幅降低鸿蒙应用开发成本。
更多推荐
所有评论(0)