119 lines
2.5 KiB
Markdown
119 lines
2.5 KiB
Markdown
|
|
# main.dart 与认证模块耦合
|
||
|
|
|
||
|
|
## 问题描述
|
||
|
|
|
||
|
|
当前 `main.dart` 直接依赖了 `AuthBloc` 和 `AuthStarted`,违反了依赖反转原则。
|
||
|
|
|
||
|
|
## 当前代码
|
||
|
|
|
||
|
|
```dart
|
||
|
|
// main.dart
|
||
|
|
import 'features/auth/presentation/bloc/auth_bloc.dart';
|
||
|
|
import 'features/auth/presentation/bloc/auth_event.dart';
|
||
|
|
|
||
|
|
void main() async {
|
||
|
|
// ...
|
||
|
|
final authBloc = sl<AuthBloc>();
|
||
|
|
authBloc.add(AuthStarted());
|
||
|
|
runApp(LinksyApp(authBloc: authBloc));
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## 问题
|
||
|
|
|
||
|
|
1. **启动逻辑与认证模块耦合**
|
||
|
|
- main.dart 需要知道 `AuthBloc` 的存在
|
||
|
|
- 需要知道 `AuthStarted` 事件
|
||
|
|
- 需要手动触发启动事件
|
||
|
|
|
||
|
|
2. **AuthBloc 被暴露3层**
|
||
|
|
```
|
||
|
|
main.dart → LinksyApp → createAppRouter → redirect()
|
||
|
|
```
|
||
|
|
每层都传 authBloc,不优雅
|
||
|
|
|
||
|
|
## 建议方案
|
||
|
|
|
||
|
|
### 1. 启动逻辑下沉到 LinksyApp
|
||
|
|
|
||
|
|
```dart
|
||
|
|
// main.dart
|
||
|
|
void main() async {
|
||
|
|
WidgetsFlutterBinding.ensureInitialized();
|
||
|
|
await configureDependencies();
|
||
|
|
await AppConstants.init();
|
||
|
|
runApp(LinksyApp());
|
||
|
|
}
|
||
|
|
|
||
|
|
// app.dart (LinksyApp)
|
||
|
|
class LinksyApp extends StatelessWidget {
|
||
|
|
@override
|
||
|
|
Widget build(BuildContext context) {
|
||
|
|
final authBloc = sl<AuthBloc>();
|
||
|
|
authBloc.add(AuthStarted());
|
||
|
|
|
||
|
|
return BlocProvider.value(
|
||
|
|
value: authBloc,
|
||
|
|
child: // ...
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### 2. 路由守卫由 LinksyApp 内部管理
|
||
|
|
|
||
|
|
```dart
|
||
|
|
// app.dart
|
||
|
|
class LinksyApp extends StatelessWidget {
|
||
|
|
@override
|
||
|
|
Widget build(BuildContext context) {
|
||
|
|
return BlocListener<AuthBloc, AuthState>(
|
||
|
|
listener: (context, state) {
|
||
|
|
final router = GoRouter.of(context);
|
||
|
|
if (state is AuthUnauthenticated) {
|
||
|
|
router.go(AppRoutes.authLogin);
|
||
|
|
} else if (state is AuthAuthenticated) {
|
||
|
|
if (router.matchedLocation == AppRoutes.authLogin) {
|
||
|
|
router.go(AppRoutes.homeMain);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
child: MaterialApp.router(
|
||
|
|
routerConfig: createAppRouter(),
|
||
|
|
),
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### 3. createAppRouter 不再需要 authBloc 参数
|
||
|
|
|
||
|
|
```dart
|
||
|
|
// app_router.dart
|
||
|
|
GoRouter createAppRouter() {
|
||
|
|
return GoRouter(
|
||
|
|
// 不再有 redirect 回调
|
||
|
|
// 路由守卫由 BlocListener 在 LinksyApp 统一处理
|
||
|
|
);
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## 收益
|
||
|
|
|
||
|
|
| 收益 | 说明 |
|
||
|
|
|------|------|
|
||
|
|
| 解耦 | main.dart 完全不知道 AuthBloc 存在 |
|
||
|
|
| 单一职责 | LinksyApp 统一管理状态监听和路由跳转 |
|
||
|
|
| 易测试 | main.dart 不再需要 mock AuthBloc |
|
||
|
|
|
||
|
|
## 涉及文件
|
||
|
|
|
||
|
|
- `apps/lib/main.dart`
|
||
|
|
- `apps/lib/app/app.dart`
|
||
|
|
- `apps/lib/app/router/app_router.dart`
|
||
|
|
- `apps/lib/features/auth/presentation/bloc/auth_bloc.dart`
|
||
|
|
|
||
|
|
## 状态
|
||
|
|
|
||
|
|
- [ ] 待修复
|