Flutter 架构实践:从 0 到 1 构建智能眼镜应用

目录

写在前面

一、架构设计的核心原则

二、五层架构详解

2.1 第一层:应用入口层

2.2 第二层:业务层

2.3 第三层:业务组件层

2.4 第四层:中间件层

2.5 第五层:基础组件层

三、启动流程:从冷启动到首页

四、状态管理:MVVM + Provider 的实践

五、跨模块通信:事件总线模式

六、总结

————————参考————————

业务需求脑图

源码 Monorepo 多包管理架构

Flutter 平台架构图

Android 平台架构图


写在前面

        作为一个面向智能眼镜设备的 Flutter 应用,MYGlass 的架构设计经历了多次迭代。从最初简单的模块化结构,到现在的多层组件化设计,我们踩过不少坑,也积累了一些经验。这篇文章想和大家分享一下我们在架构设计上的思考和实践。

一、架构设计的核心原则

        在开始设计架构之前,我们明确了几个核心原则:

  1. 高内聚低耦合:每个模块只负责自己的领域,避免跨模块的直接依赖;
  2. 可扩展性:新功能可以快速加入,不影响现有代码;
  3. 可测试性:模块之间依赖抽象,方便单元测试和集成测试;
  4. 渐进式分层:从底层到上层,依赖关系清晰。

二、五层架构详解

2.1 第一层:应用入口层

        这是整个应用的起点,包含三个文件,分别是国内版 main.dart、国际版 main_intl.dart、多版本共有main_app.dart,如下是国内版 main.dart 入口:

// main.dart - 国内版入口
void main() async {
  AppFlavor.appFlavor = Flavor.cn;
  await runMyApp(ModuleRoutesCn.routes, initFlavorImpl: () async {
    await _initMicrosoftSpeech();
    await _initBaiduMap();
  });
}
  • 通过 Flavor 区分国内版和国际版;
  • initFlavorImpl 允许不同版本初始化不同的 SDK;
  • 所有初始化逻辑都在 main_app.dart 中统一管理。

2.2 第二层:业务层

        这是应用的核心,包含了所有业务模块:

模块

功能定位

核心职责

mb_app

主应用

首页、设备管理、相册、联系人、通知、电话转写、设置等通用功能

mb_account

用户体系

登录、注册、用户信息管理

mb_assistant

AI 助手

语音交互、图像识别、智能问答等 AI Agent 功能

mb_teleprompter

提词器

演讲提词、实时字幕

mb_translate

翻译服务

实时翻译、语音转写

mb_live

直播模块

视频直播、推流

mb_notes

记录功能

AI 助手记录、翻译记录、语音录入

        实际场景:比如 AI 助手模块,它需要和蓝牙通信、语音服务、摄像头服务等多个组件交互,但这些依赖都通过抽象接口注入,模块本身不直接依赖具体实现。

2.3 第三层:业务组件层

        这一层封装了与硬件和第三方服务相关的能力:

// 蓝牙组件示例
class BTReceiveDataService {
  static final instance = BTReceiveDataService._();
  
  Stream<Map<String, dynamic>> get req => _reqController.stream;
  Stream<ConnectState?> get connectState => _connectController.stream;
  
  // 订阅眼镜发送的指令
  void listenToDeviceCommands() {
    _eventChannel.receiveBroadcastStream().listen((event) {
      final type = event['type'] as String;
      switch (type) {
        case 'simultaneousAction':
          _handleTranslateEvent(event);
          break;
        case 'teleprompterActionReq':
          _handleTeleprompterEvent(event);
          break;
      }
    });
  }
}
  • 每个组件都是单例,避免重复创建;
  • 通过 Stream 实现响应式通信;
  • 抽象硬件差异,提供统一接口。

2.4 第四层:中间件层

这一层包含基础工具和路由管理:

mb_base 的核心功能:

  • 全局常量定义(颜色、尺寸、URL 配置)
  • 生命周期管理(应用前后台监听)
  • 放置各模块可共用的代码

mb_router 使用 GoRouter 实现声明式路由:

class MainRouter {
  static GoRouter createRouter(List<RouteBase> moduleRoutes) {
    return GoRouter(
      navigatorKey: MBToast.rootNavigatorKey,
      initialLocation: '/',
      observers: [MyRouteObserver()],
      routes: [
        GoRoute(path: '/', builder: (_, __) => const SplashPage()),
        ...moduleRoutes,
      ],
    );
  }
}

2.5 第五层:基础组件层

        这是整个应用的基石,包含六大核心组件:

组件

作用

技术选型

mb_ui

UI 组件库

自定义 Widget

mb_log

日志系统

自定义实现

mb_sp

本地存储

SharedPreferences

mb_db

数据库

Drift

mb_network

网络请求

Dio

mb_eventbus

事件总线

基于 Stream 自定义实现

网络层封装示例

class NetworkClient {
  Future<Result<dynamic, NetworkError>> request(Requestable request) async {
    try {
      final response = await _dio.request(
        request.url,
        data: request.parameters,
        options: Options(method: request.method.rawValue),
      );
      return Success(response.data);
    } on DioException catch (e) {
      return Failure(NetworkError.fromDio(e));
    }
  }
}

三、启动流程:从冷启动到首页

        应用启动是一个复杂的过程,我们把它分成了四个阶段:

阶段1: Flutter引擎初始化
    ↓
阶段2: 核心服务启动(主题、语言、日志、存储)
    ↓
阶段3: 业务服务启动(网络、登录状态、设备管理)
    ↓
阶段4: 后台服务启动(三方SDK、任务管理器)

        关键代码

// main_app.dart
Future<void> runMyApp(List<RouteBase> moduleRoutes) async {
  // 阶段1:绑定引擎
  WidgetsFlutterBinding.ensureInitialized();
  
  // 阶段2:核心服务
  await themeProvider.loadTheme();
  await LogManager().initialize();
  await SPUtils.init();
  
  // 阶段3:业务服务
  NetworkClient.init(baseUrl: Config.accountV2HostProd);
  await loginViewModel.initData();
  
  // 启动应用
  runApp(MultiProvider(providers: [...], child: MyApp()));
  
  // 阶段4:后台服务
  WidgetsBinding.instance.addPostFrameCallback((_) {
    await MBTaskManager.instance.init();
  });
}

四、状态管理:MVVM + Provider 的实践

        我们采用了 MVVM 模式,配合 Provider 进行状态管理:

abstract class BaseViewModel<T> extends ChangeNotifier {
  ViewState<T> _state = const Idle();
  
  Future<void> safeRequest(Future<Result<T?, NetworkError>> Function() request) async {
    try {
      setLoading();
      final result = await request();
      result.fold(
        onSuccess: (data) => setSuccess(data),
        onFailure: (e) => setError(e),
      );
    } catch (e) {
      setError(e);
    }
  }
}

        使用示例

class LoginViewModel extends BaseViewModel<LoginResponse> {
  Future<void> login(String phone, String code) async {
    await safeRequest(() => LoginRequest(phone, code).execute());
  }
}

五、跨模块通信:事件总线模式

        当多个模块之间需要通信,但又不想产生直接依赖时,事件总线是个好选择:

// 定义事件
class TokenInvalidEvent extends AppEvent {
  final int code;
  final String message;
  TokenInvalidEvent(this.code, {this.message = ''});
}

// 触发事件
AppEventBus.instance.fire(TokenInvalidEvent(401, message: '登录过期'));

// 监听事件
AppEventBus.instance.on<TokenInvalidEvent>().listen((event) {
  router.go('/login');
});

六、总结

        架构设计不是一蹴而就的,它需要随着业务发展不断演进。MYGlass 的五层架构是我们在实践中逐步完善的结果,虽然还有不少可以改进的地方,但总体来说满足了当前的业务需求,也为未来的扩展打下了良好基础。

        如果你正在开发类似的 Flutter 应用,希望这篇文章能给你一些启发。架构没有银弹,适合自己业务的才是最好的。


————————参考————————

业务需求脑图

源码 Monorepo 多包管理架构

Flutter 平台架构图

Android 平台架构图

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值