Flutter应用架构完全指南

发布时间:2026/5/24 4:53:30

Flutter应用架构完全指南 Flutter应用架构完全指南引言良好的应用架构是Flutter项目成功的关键。本文将深入探讨Flutter应用的架构设计模式、最佳实践和代码组织策略帮助你构建可维护、可扩展的Flutter应用。一、架构模式概述1.1 MVC模式// Model class User { final String id; final String name; User({required this.id, required this.name}); } // View class UserView extends StatelessWidget { const UserView({super.key}); override Widget build(BuildContext context) { return const Placeholder(); } } // Controller class UserController { final UserRepository _repository; UserController(this._repository); FutureUser getUser(String id) async { return await _repository.fetchUser(id); } }1.2 MVP模式// View abstract class UserView { void showUser(User user); void showError(String message); } // Presenter class UserPresenter { final UserView _view; final UserRepository _repository; UserPresenter(this._view, this._repository); Futurevoid loadUser(String id) async { try { final user await _repository.fetchUser(id); _view.showUser(user); } catch (e) { _view.showError(e.toString()); } } }1.3 MVVM模式// ViewModel class UserViewModel extends ChangeNotifier { final UserRepository _repository; User? _user; User? get user _user; UserViewModel(this._repository); Futurevoid loadUser(String id) async { _user await _repository.fetchUser(id); notifyListeners(); } } // View class UserPage extends ConsumerWidget { const UserPage({super.key}); override Widget build(BuildContext context, WidgetRef ref) { final viewModel ref.watch(userViewModelProvider); return Scaffold( body: viewModel.user ! null ? Text(viewModel.user!.name) : const CircularProgressIndicator(), ); } }1.4 Clean Architecturelib/ ├── presentation/ │ ├── pages/ │ ├── widgets/ │ └── viewmodels/ ├── domain/ │ ├── entities/ │ ├── usecases/ │ └── repositories/ ├── data/ │ ├── repositories/ │ ├── datasources/ │ └── models/ └── core/ ├── network/ ├── utils/ └── constants/二、代码组织2.1 项目结构lib/ ├── main.dart ├── app/ │ ├── app.dart │ └── routes.dart ├── features/ │ ├── auth/ │ │ ├── presentation/ │ │ ├── domain/ │ │ └── data/ │ └── home/ │ ├── presentation/ │ ├── domain/ │ └── data/ ├── shared/ │ ├── widgets/ │ ├── utils/ │ └── constants/ └── dependencies/ └── injection_container.dart2.2 功能模块划分// features/auth/presentation/pages/login_page.dart class LoginPage extends StatelessWidget { const LoginPage({super.key}); override Widget build(BuildContext context) { return Scaffold( body: LoginForm(), ); } } // features/auth/presentation/widgets/login_form.dart class LoginForm extends StatefulWidget { const LoginForm({super.key}); override StateLoginForm createState() _LoginFormState(); } // features/auth/domain/usecases/login_usecase.dart class LoginUsecase { final AuthRepository repository; LoginUsecase(this.repository); FutureUser call(String email, String password) async { return await repository.login(email, password); } }三、状态管理策略3.1 选择合适的状态管理// 简单状态 - 使用setState class CounterWidget extends StatefulWidget { const CounterWidget({super.key}); override StateCounterWidget createState() _CounterWidgetState(); } class _CounterWidgetState extends StateCounterWidget { int _count 0; void _increment() setState(() _count); override Widget build(BuildContext context) { return Text(Count: $_count); } } // 中等复杂度 - 使用Provider class UserProvider extends ChangeNotifier { User? _user; User? get user _user; Futurevoid login(String email, String password) async { _user await api.login(email, password); notifyListeners(); } } // 复杂应用 - 使用Riverpod final userProvider FutureProviderUser((ref) async { return await api.fetchUser(); });3.2 状态分层// UI状态 final uiStateProvider StateProviderUIState((ref) UIState()); // 业务状态 final userProvider StateNotifierProviderUserNotifier, UserState( (ref) UserNotifier(ref.read(apiProvider)), ); // 全局状态 final themeProvider StateProviderThemeMode((ref) ThemeMode.light);四、依赖注入4.1 使用GetItimport package:get_it/get_it.dart; final sl GetIt.instance; void init() { sl.registerLazySingletonApiService(() ApiServiceImpl()); sl.registerLazySingletonUserRepository(() UserRepositoryImpl(sl())); sl.registerFactoryLoginUsecase(() LoginUsecase(sl())); } // 使用 final usecase slLoginUsecase();4.2 使用Riverpodfinal apiProvider ProviderApiService((ref) ApiServiceImpl()); final userRepositoryProvider ProviderUserRepository((ref) { final api ref.watch(apiProvider); return UserRepositoryImpl(api); }); final loginUsecaseProvider ProviderLoginUsecase((ref) { final repository ref.watch(userRepositoryProvider); return LoginUsecase(repository); });五、路由管理5.1 使用GoRouterfinal router GoRouter( routes: [ GoRoute( path: /, builder: (context, state) const HomePage(), ), GoRoute( path: /login, builder: (context, state) const LoginPage(), ), GoRoute( path: /profile/:userId, builder: (context, state) { final userId state.pathParameters[userId]!; return ProfilePage(userId: userId); }, ), ], ); void main() { runApp( MaterialApp.router( routerConfig: router, ), ); }5.2 嵌套路由final router GoRouter( routes: [ ShellRoute( builder: (context, state, child) { return ScaffoldWithNavBar(child: child); }, routes: [ GoRoute( path: /, builder: (context, state) const HomePage(), ), GoRoute( path: /profile, builder: (context, state) const ProfilePage(), ), ], ), ], );六、网络层设计6.1 封装API服务class ApiService { final Dio _dio; ApiService(this._dio); FutureUser fetchUser(String id) async { final response await _dio.get(/users/$id); return User.fromJson(response.data); } FutureListUser fetchUsers() async { final response await _dio.get(/users); return (response.data as List).map((json) User.fromJson(json)).toList(); } }6.2 错误处理class ApiException implements Exception { final String message; final int? statusCode; ApiException(this.message, [this.statusCode]); override String toString() ApiException: $message (status: $statusCode); } class ApiService { FutureUser fetchUser(String id) async { try { final response await _dio.get(/users/$id); if (response.statusCode ! 200) { throw ApiException(请求失败, response.statusCode); } return User.fromJson(response.data); } catch (e) { throw ApiException(网络错误: $e); } } }七、数据持久化7.1 使用Hiveclass HiveService { Futurevoid init() async { await Hive.initFlutter(); Hive.registerAdapter(UserAdapter()); await Hive.openBoxUser(users); } Futurevoid saveUser(User user) async { final box Hive.boxUser(users); await box.put(user.id, user); } User? getUser(String id) { final box Hive.boxUser(users); return box.get(id); } }7.2 使用SharedPreferencesclass PreferencesService { final SharedPreferences _prefs; PreferencesService(this._prefs); String? get token _prefs.getString(token); Futurevoid setToken(String token) _prefs.setString(token, token); Futurevoid clearToken() _prefs.remove(token); }八、错误边界8.1 使用ErrorWidgetclass ErrorBoundary extends StatelessWidget { const ErrorBoundary({ super.key, required this.child, required this.onError, }); final Widget child; final Widget Function(Object error) onError; override Widget build(BuildContext context) { return ErrorWidget.builder( (error, stackTrace) { return onError(error); }, child: child, ); } }8.2 全局错误处理void main() { FlutterError.onError (details) { FlutterError.presentError(details); // 上报错误到监控平台 ErrorReportingService.report(details.exception, details.stack); }; runApp(const MyApp()); }九、性能优化9.1 减少Widget重建// 使用const构造函数 const Text(Hello); // 使用Select优化Provider SelectorCounterProvider, int( selector: (context, provider) provider.count, builder: (context, count, child) Text(Count: $count), ); // 使用const避免不必要重建 const MyWidget();9.2 列表优化// 使用ListView.builder ListView.builder( itemCount: items.length, itemBuilder: (context, index) ItemWidget(item: items[index]), ); // 使用AutomaticKeepAliveClientMixin class MyTabView extends StatefulWidget { const MyTabView({super.key}); override StateMyTabView createState() _MyTabViewState(); } class _MyTabViewState extends StateMyTabView with AutomaticKeepAliveClientMixin { override bool get wantKeepAlive true; override Widget build(BuildContext context) { super.build(context); return const Placeholder(); } }十、测试策略10.1 单元测试void main() { group(LoginUsecase, () { late LoginUsecase usecase; late MockUserRepository mockRepository; setUp(() { mockRepository MockUserRepository(); usecase LoginUsecase(mockRepository); }); test(登录成功, () async { when(mockRepository.login(email, password)) .thenAnswer((_) async User(id: 1, name: Test)); final user await usecase(email, password); expect(user.id, 1); verify(mockRepository.login(email, password)).called(1); }); }); }10.2 Widget测试void main() { testWidgets(LoginForm测试, (WidgetTester tester) async { await tester.pumpWidget(const MaterialApp(home: LoginForm())); expect(find.text(登录), findsOneWidget); await tester.enterText(find.byType(TextField).first, testexample.com); await tester.enterText(find.byType(TextField).last, password); await tester.tap(find.text(登录)); await tester.pump(); }); }总结良好的应用架构是Flutter项目成功的关键通过以下实践可以提升项目质量选择合适的架构模式MVC、MVP、MVVM或Clean Architecture合理组织代码按功能模块划分选择合适的状态管理根据复杂度选择方案使用依赖注入提高代码可测试性优化性能减少不必要的重建编写测试保证代码质量通过遵循这些最佳实践你可以构建可维护、可扩展的Flutter应用。

相关新闻