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

Flutter 架构实践:从 0 到 1 构建智能眼镜应用 目录写在前面一、架构设计的核心原则二、五层架构详解2.1 第一层应用入口层2.2 第二层业务层2.3 第三层业务组件层2.4 第四层中间件层2.5 第五层基础组件层三、启动流程从冷启动到首页四、状态管理MVVM Provider 的实践五、跨模块通信事件总线模式六、总结————————参考————————业务需求脑图源码 Monorepo 多包管理架构Flutter 平台架构图Android 平台架构图写在前面作为一个面向智能眼镜设备的 Flutter 应用MYGlass 的架构设计经历了多次迭代。从最初简单的模块化结构到现在的多层组件化设计我们踩过不少坑也积累了一些经验。这篇文章想和大家分享一下我们在架构设计上的思考和实践。一、架构设计的核心原则在开始设计架构之前我们明确了几个核心原则高内聚低耦合每个模块只负责自己的领域避免跨模块的直接依赖可扩展性新功能可以快速加入不影响现有代码可测试性模块之间依赖抽象方便单元测试和集成测试渐进式分层从底层到上层依赖关系清晰。二、五层架构详解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_assistantAI 助手语音交互、图像识别、智能问答等 AI Agent 功能mb_teleprompter提词器演讲提词、实时字幕mb_translate翻译服务实时翻译、语音转写mb_live直播模块视频直播、推流mb_notes记录功能AI 助手记录、翻译记录、语音录入实际场景比如 AI 助手模块它需要和蓝牙通信、语音服务、摄像头服务等多个组件交互但这些依赖都通过抽象接口注入模块本身不直接依赖具体实现。2.3 第三层业务组件层这一层封装了与硬件和第三方服务相关的能力// 蓝牙组件示例 class BTReceiveDataService { static final instance BTReceiveDataService._(); StreamMapString, dynamic get req _reqController.stream; StreamConnectState? 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(ListRouteBase moduleRoutes) { return GoRouter( navigatorKey: MBToast.rootNavigatorKey, initialLocation: /, observers: [MyRouteObserver()], routes: [ GoRoute(path: /, builder: (_, __) const SplashPage()), ...moduleRoutes, ], ); } }2.5 第五层基础组件层这是整个应用的基石包含六大核心组件组件作用技术选型mb_uiUI 组件库自定义 Widgetmb_log日志系统自定义实现mb_sp本地存储SharedPreferencesmb_db数据库Driftmb_network网络请求Diomb_eventbus事件总线基于 Stream 自定义实现网络层封装示例class NetworkClient { FutureResultdynamic, 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 Futurevoid runMyApp(ListRouteBase 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 BaseViewModelT extends ChangeNotifier { ViewStateT _state const Idle(); Futurevoid safeRequest(FutureResultT?, 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 BaseViewModelLoginResponse { Futurevoid 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.onTokenInvalidEvent().listen((event) { router.go(/login); });六、总结架构设计不是一蹴而就的它需要随着业务发展不断演进。MYGlass 的五层架构是我们在实践中逐步完善的结果虽然还有不少可以改进的地方但总体来说满足了当前的业务需求也为未来的扩展打下了良好基础。如果你正在开发类似的 Flutter 应用希望这篇文章能给你一些启发。架构没有银弹适合自己业务的才是最好的。————————参考————————业务需求脑图源码 Monorepo 多包管理架构Flutter 平台架构图Android 平台架构图