Skip to content

BasePage 架构

BasePage 是 flu-cli 生成项目的核心基类,它提供了一套标准化的页面开发模式,集成了生命周期管理、状态绑定、UI 状态反馈(Loading/Error/Empty)等常用功能。

架构设计

BasePage 采用 MVVM (Model-View-ViewModel) 架构模式,将页面逻辑与 UI 分离。

  • BasePage: StatefulWidget 的子类,负责定义页面参数。
  • BasePageState: State 的子类,负责构建 UI 和绑定 ViewModel。
  • BaseViewModel: 负责业务逻辑和状态管理。
mermaid
classDiagram
    StatefulWidget <|-- BasePage
    State <|-- BasePageState
    ChangeNotifier <|-- BaseViewModel
    
    BasePage ..> BaseViewModel : 泛型依赖
    BasePageState --> BaseViewModel : 持有实例
    BasePageState ..> BasePage : 关联

核心特性

1. 自动化的 ViewModel 管理

BasePageState 会自动管理 ViewModel 的生命周期:

  • 创建: 在 initState 中调用 createViewModel()
  • 初始化: 自动调用 viewModel.onInit()
  • 销毁: 在 dispose 中自动调用 viewModel.dispose()
  • 监听: 自动监听 ViewModel 的变化并刷新 UI。
dart
class HomePage extends BasePage<HomeViewModel> {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends BasePageState<HomeViewModel, HomePage> {
  @override
  HomeViewModel createViewModel() => HomeViewModel();

  @override
  Widget buildContent(BuildContext context) {
    // ViewModel 已自动创建并绑定,可直接使用
    return Text(viewModel.title);
  }
}

2. 内置状态视图

BasePageState 根据 ViewModel 的状态(ViewState)自动切换 UI:

  • Loading: viewModel.isLoading 为 true 时显示。
  • Error: viewModel.isError 为 true 时显示。
  • Empty: isEmptyContent 返回 true 时显示。
  • Content: 默认显示 buildContent 返回的内容。

你可以在 BasePageState 中重写这些构建方法来自定义视图:

dart
@override
Widget buildLoading() {
  return const Center(child: CupertinoActivityIndicator());
}

@override
Widget buildError() {
  return ErrorWidget(
    message: viewModel.errorMessage,
    onRetry: viewModel.refreshData,
  );
}

3. 可配置的 UI 选项

通过重写 getter 方法,可以快速配置页面外观:

dart
@override
bool get showAppBar => true; // 是否显示 AppBar

@override
String get title => '首页'; // AppBar 标题

@override
bool get showBackButton => false; // 是否显示返回按钮

@override
Color? get backgroundColor => Colors.grey[100]; // 背景色

@override
bool get useSafeArea => true; // 是否使用 SafeArea

生命周期

BasePage 的生命周期与 Flutter 原生生命周期紧密结合,并扩展了 ViewModel 的钩子:

  1. initState:
    • 创建 ViewModel
    • 绑定监听器
    • 调用 viewModel.onInit()
  2. build:
    • 根据状态判断显示 Loading/Error/Empty 或 Content
  3. dispose:
    • 移除监听器
    • 调用 viewModel.dispose()

最佳实践

1. 保持 buildContent 纯净

buildContent 只应包含构建成功状态 UI 的逻辑。Loading 和 Error 状态由基类处理。

2. 使用 ViewModel 处理逻辑

不要在 UI 层处理复杂的业务逻辑。将数据获取、转换、校验等逻辑放入 ViewModel。

dart
// ❌ 错误做法
onPressed: () async {
  setState(() => _loading = true);
  await http.post(...);
  setState(() => _loading = false);
}

// ✅ 正确做法
onPressed: viewModel.submitForm

3. 全局主题配置

推荐使用 StatusViewsTheme 扩展来配置全局的 Loading、Error 和 Empty 视图,而不是在每个页面重写。

dart
// 在 main.dart 或 app.dart 中配置主题
ThemeData(
  extensions: [
    StatusViewsTheme(
      loadingBuilder: (context) => GlobalLoading(),
      errorBuilder: (context, msg) => GlobalError(msg),
      emptyBuilder: (context) => GlobalEmpty(),
    ),
  ],
)

Released under the MIT License.