Flutter for OpenHarmony:从零搭建今日资讯App(一)项目初始化
本文介绍了Flutter新闻应用开发的初始搭建过程。首先检查Flutter环境并创建项目,配置必要的依赖包如网络请求、状态管理和图片缓存等。然后规划了清晰的项目目录结构,包括模型、服务、状态管理、页面和组件等分层架构。最后创建了应用入口文件和主题管理模块,支持深色/浅色模式切换和本地存储功能,为后续开发奠定基础。整个搭建过程注重代码组织性和可维护性,采用了Provider状态管理和Material

这是一个完整的Flutter新闻应用开发系列教程。今天从项目初始化开始,搭建好基础框架,为后续开发做准备。
环境检查
首先确认Flutter环境是否正常:
flutter doctor
这个命令会检查Flutter SDK、Android工具链、iOS工具链、编辑器插件等。如果有问题会给出明确提示和解决方案。
检查要点:
- Flutter SDK是否安装
- Android Studio是否配置
- Xcode是否安装(macOS)
- VS Code插件是否安装
创建项目
使用Flutter命令创建新项目:
flutter create flutter_application_1
cd flutter_application_1
项目结构说明:
lib/- Dart代码目录,所有业务代码都在这里pubspec.yaml- 项目配置文件,管理依赖和资源android/- Android平台代码ios/- iOS平台代码test/- 测试代码目录
创建完成后,可以先运行一下看看默认的示例应用:
flutter run
配置项目依赖
打开pubspec.yaml,这是项目的配置文件。我们需要添加应用所需的依赖包:
name: flutter_application_1
description: 今日资讯 - Flutter跨平台新闻应用
publish_to: 'none'
version: 1.0.0+1
environment:
sdk: '>=3.4.0 <4.0.0'
dependencies:
flutter:
sdk: flutter
# UI组件
cupertino_icons: ^1.0.6
# 网络请求
http: ^1.1.0
# 状态管理
provider: ^6.1.1
# 本地存储
shared_preferences: ^2.2.2
# 图片缓存
cached_network_image: ^3.3.1
shimmer: ^3.0.0
flutter_staggered_grid_view: ^0.7.0
# 工具类
intl: ^0.19.0
url_launcher: ^6.2.4
share_plus: ^7.2.2
pull_to_refresh: ^2.0.0
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^3.0.0
flutter:
uses-material-design: true
依赖说明:
http- 网络请求库,用于调用API获取新闻数据provider- 状态管理方案,管理应用状态shared_preferences- 本地键值对存储,保存用户设置cached_network_image- 图片缓存库,提升图片加载速度intl- 日期格式化和国际化支持share_plus- 系统分享功能url_launcher- 打开外部链接
安装依赖:
flutter pub get
这个命令会下载所有依赖包,可能需要几分钟时间。
规划目录结构
良好的目录结构是项目可维护性的基础。创建以下目录:
mkdir -p lib/models lib/services lib/providers lib/screens lib/widgets
目录职责划分:
models/- 数据模型,定义新闻、用户等数据结构services/- API调用和业务逻辑,封装网络请求providers/- 状态管理,使用Provider管理全局状态screens/- 页面,每个页面一个文件widgets/- 可复用组件,如新闻卡片、分类标签等
这种分层架构让代码职责清晰,便于团队协作和后期维护。
编写应用入口
创建lib/main.dart,这是应用的入口文件:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'providers/theme_provider.dart';
import 'providers/news_provider.dart';
import 'providers/favorites_provider.dart';
import 'screens/splash_screen.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => ThemeProvider()),
ChangeNotifierProvider(create: (_) => NewsProvider()),
ChangeNotifierProvider(create: (_) => FavoritesProvider()),
],
child: Consumer<ThemeProvider>(
builder: (context, themeProvider, child) {
return MaterialApp(
title: '今日资讯',
debugShowCheckedModeBanner: false,
theme: themeProvider.lightTheme,
darkTheme: themeProvider.darkTheme,
themeMode: themeProvider.themeMode,
home: const SplashScreen(),
);
},
),
);
}
}
代码解析:
MultiProvider- 注册多个Provider,让全局都能访问这些状态ThemeProvider- 管理应用主题(深色/浅色模式)NewsProvider- 管理新闻数据和加载状态FavoritesProvider- 管理收藏数据Consumer<ThemeProvider>- 监听主题变化,自动更新UIdebugShowCheckedModeBanner: false- 隐藏右上角的Debug标签themeMode- 支持系统、浅色、深色三种主题模式
创建ThemeProvider
创建lib/providers/theme_provider.dart,管理应用主题:
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
class ThemeProvider extends ChangeNotifier {
ThemeMode _themeMode = ThemeMode.system;
ThemeMode get themeMode => _themeMode;
ThemeProvider() {
_loadThemeMode();
}
Future<void> _loadThemeMode() async {
final prefs = await SharedPreferences.getInstance();
final themeModeString = prefs.getString('themeMode') ?? 'system';
_themeMode = ThemeMode.values.firstWhere(
(e) => e.toString() == 'ThemeMode.$themeModeString',
orElse: () => ThemeMode.system,
);
notifyListeners();
}
Future<void> setThemeMode(ThemeMode mode) async {
_themeMode = mode;
final prefs = await SharedPreferences.getInstance();
await prefs.setString('themeMode', mode.toString().split('.').last);
notifyListeners();
}
ThemeData get lightTheme => ThemeData(
useMaterial3: true,
brightness: Brightness.light,
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.blue,
brightness: Brightness.light,
),
);
ThemeData get darkTheme => ThemeData(
useMaterial3: true,
brightness: Brightness.dark,
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.blue,
brightness: Brightness.dark,
),
);
}
代码解析:
ChangeNotifier- Provider的基类,提供状态通知功能_loadThemeMode()- 从本地存储读取用户上次选择的主题setThemeMode()- 切换主题并保存到本地,下次打开应用时恢复notifyListeners()- 通知所有监听者更新UIuseMaterial3: true- 使用Material Design 3最新设计规范ColorScheme.fromSeed- 从种子颜色生成完整配色方案,自动适配深浅色
创建NewsProvider
创建lib/providers/news_provider.dart,管理新闻数据:
import 'package:flutter/material.dart';
import '../models/news_article.dart';
import '../services/api_service.dart';
class NewsProvider extends ChangeNotifier {
final ApiService _apiService = ApiService();
final Map<String, List<NewsArticle>> _newsCache = {};
bool _isLoading = false;
String? _error;
bool get isLoading => _isLoading;
String? get error => _error;
List<NewsArticle> getNewsByCategory(String category) {
return _newsCache[category] ?? [];
}
Future<void> fetchNews(String category) async {
if (_newsCache.containsKey(category) && _newsCache[category]!.isNotEmpty) {
return;
}
_isLoading = true;
_error = null;
notifyListeners();
try {
List<NewsArticle> articles;
switch (category) {
case 'space':
articles = await _apiService.fetchSpaceNews();
break;
case 'tech':
articles = await _apiService.fetchTechNews();
break;
default:
articles = await _apiService.fetchSpaceNews();
}
_newsCache[category] = articles;
} catch (e) {
_error = e.toString();
} finally {
_isLoading = false;
notifyListeners();
}
}
Future<void> refreshNews(String category) async {
_newsCache.remove(category);
await fetchNews(category);
}
}
代码解析:
_newsCache- 缓存不同分类的新闻数据,避免重复请求_isLoading- 加载状态标志,用于显示加载动画_error- 错误信息,用于显示错误提示fetchNews()- 获取新闻,有缓存则直接返回,提升用户体验refreshNews()- 清除缓存并重新获取,用于下拉刷新
这种缓存机制可以大大提升应用的响应速度,用户切换分类时几乎是瞬间完成的。
创建FavoritesProvider
创建lib/providers/favorites_provider.dart,管理收藏功能:
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../models/news_article.dart';
class FavoritesProvider extends ChangeNotifier {
List<NewsArticle> _favorites = [];
List<NewsArticle> get favorites => _favorites;
FavoritesProvider() {
_loadFavorites();
}
Future<void> _loadFavorites() async {
final prefs = await SharedPreferences.getInstance();
final favoritesJson = prefs.getStringList('favorites') ?? [];
_favorites = favoritesJson
.map((json) => NewsArticle.fromJson(jsonDecode(json)))
.toList();
notifyListeners();
}
Future<void> _saveFavorites() async {
final prefs = await SharedPreferences.getInstance();
final favoritesJson = _favorites
.map((article) => jsonEncode(article.toJson()))
.toList();
await prefs.setStringList('favorites', favoritesJson);
}
bool isFavorite(String articleId) {
return _favorites.any((article) => article.id == articleId);
}
Future<void> toggleFavorite(NewsArticle article) async {
if (isFavorite(article.id)) {
_favorites.removeWhere((a) => a.id == article.id);
} else {
_favorites.insert(0, article);
}
await _saveFavorites();
notifyListeners();
}
}
代码解析:
_loadFavorites()- 从本地存储加载收藏列表,应用启动时自动调用_saveFavorites()- 保存收藏列表到本地,确保数据持久化isFavorite()- 判断文章是否已收藏,用于显示收藏按钮状态toggleFavorite()- 切换收藏状态,收藏或取消收藏jsonEncode/jsonDecode- JSON序列化和反序列化,用于存储复杂对象
配置代码检查
创建analysis_options.yaml,配置代码检查规则:
include: package:flutter_lints/flutter.yaml
linter:
rules:
prefer_const_constructors: true
prefer_const_literals_to_create_immutables: true
avoid_print: true
作用:使用Flutter官方推荐的lint规则,帮助发现代码问题,提升代码质量。
运行测试
现在可以尝试运行应用了:
flutter run
首次运行会编译整个应用,需要几分钟。后续运行会快很多,因为Flutter支持热重载。
注意:现在运行会报错,因为引用的文件还不存在(SplashScreen、NewsArticle等)。这是正常的,我们会在后续文章中逐步创建这些文件。
常见问题处理
依赖下载失败
如果在国内网络环境下,可能需要配置镜像:
export PUB_HOSTED_URL=https://pub.flutter-io.cn
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
版本冲突
如果遇到依赖版本冲突,可以使用dependency_overrides强制指定版本:
dependency_overrides:
http: ^1.1.0
Gradle下载慢
编辑android/build.gradle,添加国内镜像:
repositories {
maven { url 'https://maven.aliyun.com/repository/google' }
maven { url 'https://maven.aliyun.com/repository/jcenter' }
google()
mavenCentral()
}
项目初始化完成
现在项目基础框架已经搭建完成,包括:
✅ 环境检查 - 确认Flutter环境正常
✅ 项目创建 - 创建Flutter项目
✅ 依赖配置 - 添加所需依赖包
✅ 目录结构 - 规划清晰的目录结构
✅ 应用入口 - 配置MultiProvider和主题
✅ 三个核心Provider - 主题、新闻、收藏
✅ 代码检查 - 配置lint规则
虽然引用的文件还不存在(会报错),但框架已经搭好,后续会逐步完善。这种先搭框架再填充内容的方式,可以让我们对整个应用的架构有清晰的认识。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
在这里你可以找到更多Flutter开发资源,与其他开发者交流经验,共同进步。
更多推荐



所有评论(0)