Flutter 基于Riverpod实现一个MVVM+Repository的实用框架

523 阅读3分钟

在开发 Flutter 应用时,良好的架构设计对于项目的可维护性和可扩展性至关重要。本文将介绍一个基于 Riverpod 状态管理的 Flutter 应用架构设计方案,通过实现一系列基础类来规范化开发流程,提高代码质量。

架构概述

该架构设计主要包含以下几个核心组件:

  1. BaseState:状态管理基类
  2. BaseNotifier:状态通知器基类
  3. BaseRepository:数据仓储基类
  4. BasePage:页面视图基类

这些基类共同构成了一个完整的 MVVM + Repository 架构体系,使得业务逻辑、UI 展示和数据处理能够清晰分离。

详细设计

1. BaseState:统一的状态管理

@freezed
class BaseState<T> with _$BaseState<T> {
  const factory BaseState.initial() = Initial<T>;
  const factory BaseState.loading() = Loading<T>;
  const factory BaseState.success(T data) = Success<T>;
  const factory BaseState.error(String message) = Error<T>;
}

BaseState 使用 freezed 库实现了一个通用的状态管理类,包含四种基本状态:

  • initial:初始状态
  • loading:加载状态
  • success:成功状态(携带数据)
  • error:错误状态(携带错误信息)

这种设计让状态管理变得统一和可预测,方便处理异步操作和错误情况。

2. BaseNotifier:状态更新管理

BaseNotifier 类提供了状态更新的基本功能:

  • 统一的异步操作处理
  • 自动的加载状态管理
  • 错误处理机制

对于列表数据,还提供了特化的 BaseListNotifier 和 BasePaginatedListNotifier,支持分页加载等高级功能。

3. BaseRepository:数据访问层

abstract class BaseRepository {
  @protected
  Future<T> handleResponse<T>(Future<T> Function() request) async {
    try {
      return await request();
    } catch (e) {
      throw ApiException(message: e.toString());
    }
  }
}

BaseRepository 提供了:

  • 统一的异常处理机制
  • 标准化的 API 请求处理
  • 可复用的数据访问模式

4. BasePage:统一的页面结构

abstract class BasePage extends ConsumerWidget {
  Widget buildBody(BuildContext context, WidgetRef ref);
  PreferredSizeWidget? buildAppBar(BuildContext context, WidgetRef ref) => null;
  Widget? buildFloatingActionButton(BuildContext context, WidgetRef ref) => null;
  Widget? buildDrawer(BuildContext context, WidgetRef ref) => null;
}

BasePage 实现了:

  • 统一的页面结构
  • 集成的状态管理
  • 可定制的界面组件

使用示例

下面是一个简单的使用示例:

// 定义状态通知器
class UserNotifier extends BaseNotifier<User> {
  Future<void> loadUser() => runFuture(() => repository.getUser());
}

// 定义仓储
class UserRepository extends BaseRepository {
  Future<User> getUser() => handleResponse(() => api.fetchUser());
}

// 定义页面
class UserPage extends BasePage {
  @override
  Widget buildBody(BuildContext context, WidgetRef ref) {
    final state = ref.watch(userProvider);
    return state.when(
      initial: () => Container(),
      loading: () => CircularProgressIndicator(),
      success: (user) => UserView(user),
      error: (message) => ErrorView(message),
    );
  }
}

架构优势

  1. 代码复用:基类封装了常用功能,减少重复代码
  2. 统一规范:标准化的架构设计,提高代码可维护性
  3. 错误处理:统一的错误处理机制,提高应用稳定性
  4. 状态管理:清晰的状态管理方案,简化异步操作处理
  5. 扩展性好:基类设计合理,易于扩展新功能

最佳实践

  1. 状态管理

    • 使用 BaseState 处理所有异步操作状态
    • 善用 when/maybeWhen 方法处理不同状态
  2. 错误处理

    • 在 Repository 层统一处理 API 错误
    • 使用 ApiException 封装错误信息
  3. UI 开发

    • 继承 BasePage 创建新页面
    • 根据需要重写相应的构建方法
  4. 代码组织

    • 按功能模块组织代码
    • 保持类的单一职责

结论

这套架构设计方案通过基类的抽象和封装,为 Flutter 应用开发提供了一个清晰、可维护的代码组织方式。它不仅规范了开发流程,还提供了许多实用的功能,能够显著提高开发效率和代码质量。

在实际项目中,开发者可以根据具体需求对这些基类进行扩展和调整,但核心的架构思想和设计模式是值得参考的。通过这种方式,我们可以构建出更加健壮和可维护的 Flutter 应用。