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 的钩子:
- initState:
- 创建 ViewModel
- 绑定监听器
- 调用
viewModel.onInit()
- build:
- 根据状态判断显示 Loading/Error/Empty 或 Content
- 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.submitForm3. 全局主题配置
推荐使用 StatusViewsTheme 扩展来配置全局的 Loading、Error 和 Empty 视图,而不是在每个页面重写。
dart
// 在 main.dart 或 app.dart 中配置主题
ThemeData(
extensions: [
StatusViewsTheme(
loadingBuilder: (context) => GlobalLoading(),
errorBuilder: (context, msg) => GlobalError(msg),
emptyBuilder: (context) => GlobalEmpty(),
),
],
)