01-Flutter 鸿蒙实战 01:会说话的相册项目架构拆解

01. Flutter 鸿蒙实战 01:会说话的相册项目架构拆解

从目录、依赖、业务模块和鸿蒙工程开始,先看清一个完整 App 的骨架。

项目定位

talking_album 不是一个只展示页面的 Flutter Demo,而是一个已经接入后端、登录态、图片上传、故事生成、语音播放、视频播放和鸿蒙打包链路的客户端。pubspec.yaml 里的描述是"会说话的相册 Flutter HarmonyOS 客户端",项目目标也很清楚:把 Web 手机端的"会说话的相册"迁移到 Flutter,并让它可以运行在 HarmonyOS/OpenHarmony 工程里。

项目的入口非常轻,lib/main.dart 只负责启动应用:

dart 复制代码
import 'package:flutter/material.dart';

import 'app/app.dart';

void main() {
  runApp(const TalkingAlbumApp());
}

真正的应用初始化放在 lib/app/app.dart。这里创建 ApiClientAuthController,再通过 AuthScope 注入到整棵组件树。这样的好处是业务页面不用到处 new 网络客户端,也不用把 token 状态层层传递。

dart 复制代码
class _TalkingAlbumAppState extends State<TalkingAlbumApp> {
  late final ApiClient _apiClient;
  late final AuthController _authController;

  @override
  void initState() {
    super.initState();
    _apiClient = ApiClient();
    _authController = AuthController(
      apiClient: _apiClient,
      sessionStore: SharedPreferencesSessionStore(),
    );
    _authController.initialize();
  }
}

目录分层

项目目录按"应用入口、通用能力、业务功能、鸿蒙宿主"分层:

text 复制代码
lib/
├─ app/                 应用入口、路由表
├─ core/
│  ├─ config/           API 地址等配置
│  ├─ network/          ApiClient、错误转换
│  ├─ speech/           本地讲故事通道
│  ├─ theme/            颜色和主题
│  └─ utils/            JSON 辅助
└─ features/
   ├─ auth/             登录、注册、会话
   ├─ home/             首页
   ├─ upload/           照片上传
   ├─ stories/          故事集、详情、语音、视频
   ├─ map/              家族地图
   ├─ anniversary/      纪念日
   ├─ family/           家人列表
   ├─ notifications/    通知中心
   ├─ profile/          个人资料
   └─ shell/            顶部栏和底部导航

ohos/ 是 Flutter 鸿蒙宿主工程,不是临时目录。里面包含 EntryAbility.etsGeneratedPluginRegistrant.etsmodule.json5、资源文件和 HAP 构建产物。项目能跑在鸿蒙上,关键就在这套宿主工程和 Flutter OpenHarmony 工具链的配合。

鸿蒙侧工程

ohos/entry/src/main/ets/entryability/EntryAbility.ets 继承 FlutterAbility,并注册 Flutter 插件:

ts 复制代码
import { FlutterAbility, FlutterEngine } from '@ohos/flutter_ohos';
import { GeneratedPluginRegistrant } from '../plugins/GeneratedPluginRegistrant';

export default class EntryAbility extends FlutterAbility {
  configureFlutterEngine(flutterEngine: FlutterEngine) {
    super.configureFlutterEngine(flutterEngine)
    GeneratedPluginRegistrant.registerWith(flutterEngine)
  }
}

插件注册文件里能看到项目实际用到的鸿蒙适配插件:

ts 复制代码
flutterEngine.getPlugins()?.add(new AudioplayersPlugin());
flutterEngine.getPlugins()?.add(new ImagePickerPlugin());
flutterEngine.getPlugins()?.add(new SharedPreferencesPlugin());
flutterEngine.getPlugins()?.add(new VideoPlayerPlugin());

这说明项目并不是只用 Flutter 画 UI,还用了鸿蒙侧插件能力:本地存储、图片选择、音频播放和视频播放都要靠 OpenHarmony 适配包。

依赖选择

pubspec.yaml 中最关键的依赖是这些:

yaml 复制代码
shared_preferences_ohos:
  git:
    url: https://gitcode.com/openharmony-tpc/flutter_packages.git
    path: packages/shared_preferences/shared_preferences_ohos
image_picker:
  git:
    url: https://gitcode.com/openharmony-tpc/flutter_packages.git
    path: packages/image_picker/image_picker
audioplayers:
  git:
    url: https://gitee.com/openharmony-sig/flutter_audioplayers.git
    ref: br_audioplayers-v6.1.0_ohos
    path: packages/audioplayers
video_player:
  git:
    url: https://gitcode.com/openharmony-tpc/flutter_packages.git
    ref: br_video_player-v2.9.2_ohos
    path: packages/video_player/video_player

这类依赖不能随便替换成 pub.dev 上的普通版本。普通 Flutter 插件未必带 ohos 实现,代码能在 Android 跑,不代表能在鸿蒙工程里构建。

配图安排

完成这层结构梳理后,后面的登录会话、网络层、上传、故事、音频、视频、地图和 HAP 构建都能在同一套工程骨架里找到对应位置。

扩展拆解

进一步拆解:为什么这个架构适合继续扩展

这个项目的架构不是为了"看起来分层",而是为了后续功能继续增长。app 层只做应用装配,core 层放网络、主题、配置、语音通道,features 按业务拆分。这样新增功能时,开发者能快速判断代码应该放哪里:如果是业务页面,进入 features;如果是所有页面都要用的能力,进入 core;如果是启动、登录拦截、主题、本地化,进入 app

例如"家人列表"不是写在首页里,而是单独放到 features/family。首页只提供入口,真正的列表、邀请、权限、管理菜单都在自己的模块内。这个边界清楚后,首页不会随着功能增加变成一个巨大的文件。

text 复制代码
features/home       负责首页展示和入口跳转
features/family     负责家人列表、邀请和管理
features/stories    负责故事列表、详情、音频、视频
features/upload     负责照片选择、上传和上传列表管理

另一个关键点是 ohos 工程已经进入项目结构。Flutter 代码负责页面和业务逻辑,但鸿蒙侧仍然要处理 EntryAbility、权限、插件注册和 HAP 构建。写 Flutter 鸿蒙项目时,不能只看 lib,也要把 ohos 当作正式源码的一部分。

管理

复制代码
另一个关键点是 `ohos` 工程已经进入项目结构。Flutter 代码负责页面和业务逻辑,但鸿蒙侧仍然要处理 EntryAbility、权限、插件注册和 HAP 构建。写 Flutter 鸿蒙项目时,不能只看 `lib`,也要把 `ohos` 当作正式源码的一部分。
相关推荐
不羁的木木1 小时前
《HarmonyOS技术精讲-NearLink Kit(星闪服务)》第10篇:多设备协同——构建星闪网络实现数据同步
网络·华为·harmonyos
春卷同学1 小时前
HarmonyOS掌上记账APP开发实践第29篇:条件渲染与 ForEach — 动态 UI 的构建策略
ui·华为·harmonyos
春卷同学2 小时前
HarmonyOS掌上记账APP开发实践第22篇:Scroll + List 虚拟列表 — 长列表性能优化全攻略
性能优化·list·harmonyos
不羁的木木2 小时前
《HarmonyOS技术精讲-NearLink Kit(星闪服务)》第4篇:广播通信——一对多广播应用实现
华为·harmonyos
w139548564222 小时前
鸿蒙应用开发实战【91】— 完整功能串联从添加到换绑的全链路
华为·harmonyos·鸿蒙系统
2501_919749032 小时前
华为鸿蒙免费训练口才APP—小羊口才
华为·harmonyos
木木子222 小时前
# [特殊字符] 画画模拟器 — 鸿蒙ArkTS完整技术解析
华为·harmonyos
Helen_cai2 小时前
OpenHarmony 图片选择 & 相册相机工具封装 ImagePickerUtil(API23)
数码相机·华为·harmonyos
AD022711 小时前
22-平板上页面被拉扁-用断点布局和资源覆盖做一多适配
harmonyos·arkts·鸿蒙开发