Flutter App 架构文档

目录

  1. 概述
  2. 核心架构原则
  3. 项目结构
  4. 状态管理
  5. 网络层架构
  6. 数据层架构
  7. UI层架构
  8. 依赖注入
  9. 路由管理
  10. 错误处理
  11. 测试策略
  12. 性能优化
  13. 代码规范
  14. 部署与CI/CD

概述

一个优秀的Flutter App框架应该具备以下特征:

  • 可维护性:代码结构清晰,易于理解和修改
  • 可扩展性:能够轻松添加新功能和模块
  • 可测试性:支持单元测试、集成测试和UI测试
  • 性能优化:确保应用运行流畅,内存使用合理
  • 团队协作:统一的代码规范和开发流程

核心架构原则

1. 分层架构

┌─────────────────┐
│   Presentation  │  UI层 (Widgets, Pages, Components)
├─────────────────┤
│   Business      │ 业务逻辑层 (Use Cases, Services)
├─────────────────┤
│   Data          │ 数据层 (Repository, DataSource)
├─────────────────┤
│   Infrastructure│ 基础设施层 (Network, Storage, Platform)
└─────────────────┘

2. 关注点分离

  • UI层:只负责展示和用户交互
  • 业务层:处理业务逻辑和用例
  • 数据层:管理数据获取和存储
  • 基础设施层:提供平台相关功能

3. 依赖倒置

  • 高层模块不依赖低层模块
  • 两者都依赖于抽象接口
  • 通过依赖注入实现解耦

项目结构

lib/
├── app/                    # 应用配置
│   ├── app.dart           # 应用入口
│   ├── app_config.dart    # 应用配置
│   └── app_theme.dart     # 主题配置
├── core/                  # 核心功能
│   ├── constants/         # 常量定义
│   ├── errors/           # 错误处理
│   ├── network/          # 网络配置
│   ├── utils/            # 工具类
│   └── extensions/       # 扩展方法
├── features/             # 功能模块
│   └── [feature_name]/   # 具体功能
│       ├── data/         # 数据层
│       │   ├── datasources/
│       │   ├── models/
│       │   └── repositories/
│       ├── domain/       # 业务层
│       │   ├── entities/
│       │   ├── repositories/
│       │   └── usecases/
│       └── presentation/ # 展示层
│           ├── pages/
│           ├── widgets/
│           └── providers/
├── shared/               # 共享组件
│   ├── widgets/         # 通用组件
│   ├── services/        # 共享服务
│   └── models/          # 共享模型
└── main.dart            # 应用入口

状态管理

推荐方案:Riverpod + Freezed

// 状态定义

class UserState with _$UserState {
  const factory UserState({
    (false) bool isLoading,
    (null) User? user,
    (null) String? error,
  }) = _UserState;
}

// 状态提供者

class UserNotifier extends _$UserNotifier {
  
  UserState build() => const UserState();

  Future<void> loadUser(String userId) async {
    state = state.copyWith(isLoading: true);
    try {
      final user = await ref.read(userRepositoryProvider).getUser(userId);
      state = state.copyWith(user: user, isLoading: false);
    } catch (e) {
      state = state.copyWith(error: e.toString(), isLoading: false);
    }
  }
}

状态管理最佳实践

  1. 单一数据源:每个状态只有一个真实来源
  2. 不可变状态:使用Freezed确保状态不可变
  3. 状态分离:按功能模块分离状态
  4. 异步处理:正确处理异步操作和错误

网络层架构

1. 网络服务配置

// dio_client.dart
class DioClient {
  late Dio _dio;
  
  DioClient() {
    _dio = Dio();
    _dio.options.baseUrl = AppConfig.baseUrl;
    _dio.options.connectTimeout = const Duration(seconds: 30);
    _dio.options.receiveTimeout = const Duration(seconds: 30);
    
    // 添加拦截器
    _dio.interceptors.addAll([
      AuthInterceptor(),
      LogInterceptor(),
      ErrorInterceptor(),
    ]);
  }
  
  Dio get dio => _dio;
}

2. API服务定义

// api_service.dart
()
abstract class ApiService {
  factory ApiService(Dio dio) = _ApiService;
  
  ('/users/{id}')
  Future<UserDto> getUser(() String id);
  
  ('/users')
  Future<UserDto> createUser(() CreateUserRequest request);
}

3. 数据转换

// user_mapper.dart
class UserMapper {
  static User toEntity(UserDto dto) {
    return User(
      id: dto.id,
      name: dto.name,
      email: dto.email,
    );
  }
  
  static UserDto toDto(User entity) {
    return UserDto(
      id: entity.id,
      name: entity.name,
      email: entity.email,
    );
  }
}

数据层架构

1. Repository模式

// user_repository.dart
abstract class UserRepository {
  Future<User> getUser(String id);
  Future<List<User>> getUsers();
  Future<User> createUser(CreateUserRequest request);
  Future<void> updateUser(User user);
  Future<void> deleteUser(String id);
}

class UserRepositoryImpl implements UserRepository {
  final UserRemoteDataSource _remoteDataSource;
  final UserLocalDataSource _localDataSource;
  
  UserRepositoryImpl({
    required UserRemoteDataSource remoteDataSource,
    required UserLocalDataSource localDataSource,
  }) : _remoteDataSource = remoteDataSource,
       _localDataSource = localDataSource;
  
  
  Future<User> getUser(String id) async {
    try {
      final userDto = await _remoteDataSource.getUser(id);
      final user = UserMapper.toEntity(userDto);
      await _localDataSource.cacheUser(userDto);
      return user;
    } catch (e) {
      final cachedUser = await _localDataSource.getUser(id);
      if (cachedUser != null) {
        return UserMapper.toEntity(cachedUser);
      }
      rethrow;
    }
  }
}

2. 数据源实现

// user_remote_data_source.dart
abstract class UserRemoteDataSource {
  Future<UserDto> getUser(String id);
  Future<List<UserDto>> getUsers();
}

class UserRemoteDataSourceImpl implements UserRemoteDataSource {
  final ApiService _apiService;
  
  UserRemoteDataSourceImpl(this._apiService);
  
  
  Future<UserDto> getUser(String id) async {
    return await _apiService.getUser(id);
  }
}

UI层架构

1. 页面结构

// user_page.dart
class UserPage extends ConsumerWidget {
  const UserPage({Key? key}) : super(key: key);
  
  
  Widget build(BuildContext context, WidgetRef ref) {
    final userState = ref.watch(userNotifierProvider);
    
    return Scaffold(
      appBar: AppBar(title: const Text('用户信息')),
      body: userState.when(
        data: (user) => UserContent(user: user),
        loading: () => const LoadingWidget(),
        error: (error, stack) => ErrorWidget(error: error),
      ),
    );
  }
}

2. 组件化设计

// user_card.dart
class UserCard extends StatelessWidget {
  final User user;
  final VoidCallback? onTap;
  
  const UserCard({
    Key? key,
    required this.user,
    this.onTap,
  }) : super(key: key);
  
  
  Widget build(BuildContext context) {
    return Card(
      child: ListTile(
        leading: CircleAvatar(
          backgroundImage: NetworkImage(user.avatarUrl),
        ),
        title: Text(user.name),
        subtitle: Text(user.email),
        onTap: onTap,
      ),
    );
  }
}

依赖注入

使用Riverpod进行依赖注入

// providers.dart
final dioProvider = Provider<Dio>((ref) => DioClient().dio);

final apiServiceProvider = Provider<ApiService>((ref) {
  final dio = ref.watch(dioProvider);
  return ApiService(dio);
});

final userRemoteDataSourceProvider = Provider<UserRemoteDataSource>((ref) {
  final apiService = ref.watch(apiServiceProvider);
  return UserRemoteDataSourceImpl(apiService);
});

final userRepositoryProvider = Provider<UserRepository>((ref) {
  final remoteDataSource = ref.watch(userRemoteDataSourceProvider);
  final localDataSource = ref.watch(userLocalDataSourceProvider);
  return UserRepositoryImpl(
    remoteDataSource: remoteDataSource,
    localDataSource: localDataSource,
  );
});

路由管理

使用GoRouter进行路由管理

// app_router.dart
final appRouter = GoRouter(
  initialLocation: '/',
  routes: [
    GoRoute(
      path: '/',
      builder: (context, state) => const HomePage(),
    ),
    GoRoute(
      path: '/users',
      builder: (context, state) => const UserListPage(),
      routes: [
        GoRoute(
          path: '/:id',
          builder: (context, state) {
            final userId = state.pathParameters['id']!;
            return UserDetailPage(userId: userId);
          },
        ),
      ],
    ),
  ],
);

错误处理

1. 自定义异常类

// exceptions.dart
abstract class AppException implements Exception {
  final String message;
  final String? code;
  
  const AppException(this.message, [this.code]);
}

class NetworkException extends AppException {
  const NetworkException(super.message, [super.code]);
}

class CacheException extends AppException {
  const CacheException(super.message, [super.code]);
}

class ValidationException extends AppException {
  const ValidationException(super.message, [super.code]);
}

2. 错误处理中间件

// error_handler.dart
class ErrorHandler {
  static void handleError(Object error, StackTrace stackTrace) {
    if (error is NetworkException) {
      // 处理网络错误
      _showNetworkError(error.message);
    } else if (error is ValidationException) {
      // 处理验证错误
      _showValidationError(error.message);
    } else {
      // 处理未知错误
      _showGenericError();
    }
  }
  
  static void _showNetworkError(String message) {
    // 显示网络错误提示
  }
  
  static void _showValidationError(String message) {
    // 显示验证错误提示
  }
  
  static void _showGenericError() {
    // 显示通用错误提示
  }
}

测试策略

1. 单元测试

// user_repository_test.dart
void main() {
  group('UserRepository', () {
    late UserRepository repository;
    late MockUserRemoteDataSource mockRemoteDataSource;
    late MockUserLocalDataSource mockLocalDataSource;
    
    setUp(() {
      mockRemoteDataSource = MockUserRemoteDataSource();
      mockLocalDataSource = MockUserLocalDataSource();
      repository = UserRepositoryImpl(
        remoteDataSource: mockRemoteDataSource,
        localDataSource: mockLocalDataSource,
      );
    });
    
    test('should return user when call to remote data source is successful', () async {
      // Arrange
      const userId = '1';
      final userDto = UserDto(id: userId, name: 'Test User');
      when(() => mockRemoteDataSource.getUser(userId))
          .thenAnswer((_) async => userDto);
      
      // Act
      final result = await repository.getUser(userId);
      
      // Assert
      expect(result, equals(UserMapper.toEntity(userDto)));
    });
  });
}

2. Widget测试

// user_card_test.dart
void main() {
  testWidgets('UserCard displays user information correctly', (tester) async {
    // Arrange
    const user = User(id: '1', name: 'Test User', email: 'test@example.com');
    
    // Act
    await tester.pumpWidget(
      MaterialApp(
        home: UserCard(user: user),
      ),
    );
    
    // Assert
    expect(find.text('Test User'), findsOneWidget);
    expect(find.text('test@example.com'), findsOneWidget);
  });
}

性能优化

1. 图片优化

// 使用cached_network_image
CachedNetworkImage(
  imageUrl: user.avatarUrl,
  placeholder: (context, url) => const CircularProgressIndicator(),
  errorWidget: (context, url, error) => const Icon(Icons.error),
  memCacheWidth: 100,
  memCacheHeight: 100,
)

2. 列表优化

// 使用ListView.builder进行懒加载
ListView.builder(
  itemCount: users.length,
  itemBuilder: (context, index) {
    return UserCard(user: users[index]);
  },
)

3. 状态优化

// 使用Consumer进行局部重建
Consumer(
  builder: (context, ref, child) {
    final user = ref.watch(userProvider);
    return Text(user.name);
  },
)

代码规范

1. 命名规范

// 类名使用PascalCase
class UserRepository {}

// 变量和方法使用camelCase
String userName = 'test';
void getUserName() {}

// 常量使用UPPER_SNAKE_CASE
const String API_BASE_URL = 'https://api.example.com';

// 私有成员使用下划线前缀
String _privateVariable = 'private';

2. 文件组织

// 文件头部注释
/// 用户相关的数据模型
/// 
/// 包含用户的基本信息,如姓名、邮箱等
class User {
  // 类实现
}

3. 代码注释

/// 获取用户信息
/// 
/// [userId] 用户ID
/// 返回用户详细信息
/// 如果用户不存在则抛出[UserNotFoundException]
Future<User> getUser(String userId) async {
  // 实现
}

部署与CI/CD

1. 环境配置

// app_config.dart
class AppConfig {
  static const String baseUrl = String.fromEnvironment(
    'BASE_URL',
    defaultValue: 'https://api.example.com',
  );
  
  static const bool isDebug = bool.fromEnvironment('DEBUG', defaultValue: true);
}

2. 构建脚本

# .github/workflows/build.yml
name: Build and Test

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - uses: subosito/flutter-action@v2
      with:
        flutter-version: '3.16.0'
    - run: flutter pub get
    - run: flutter test
    - run: flutter build apk --release

总结

一个优秀的Flutter App框架应该具备:

  1. 清晰的分层架构:确保代码组织合理,职责明确
  2. 强大的状态管理:使用Riverpod等现代状态管理方案
  3. 完善的网络层:支持缓存、错误处理、拦截器等功能
  4. 可测试的代码:编写单元测试、集成测试和UI测试
  5. 性能优化:关注内存使用、渲染性能等关键指标
  6. 统一的代码规范:确保团队协作效率
  7. 自动化部署:通过CI/CD实现快速迭代

通过遵循这些架构原则和最佳实践,可以构建出高质量、可维护的Flutter应用程序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

明似水

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值