修复优化引起的 demo bug
This commit is contained in:
@@ -59,6 +59,10 @@ class LoginViewModel extends _$LoginViewModel {
|
|||||||
/// 仅用于演示路由守卫行为,正式 UI 就绪后删除此方法,改用 [login]。
|
/// 仅用于演示路由守卫行为,正式 UI 就绪后删除此方法,改用 [login]。
|
||||||
/// 正式 [login] 成功后同样需要调用 [AuthNotifier.login] 更新守卫状态。
|
/// 正式 [login] 成功后同样需要调用 [AuthNotifier.login] 更新守卫状态。
|
||||||
Future<void> demoLogin() async {
|
Future<void> demoLogin() async {
|
||||||
|
// 防止连点重入:第一次调用未完成前忽略后续调用
|
||||||
|
if (state.isLoading) return;
|
||||||
|
state = state.copyWith(isLoading: true, error: null);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final storageApi = ref.read(storageSdkProvider);
|
final storageApi = ref.read(storageSdkProvider);
|
||||||
final storageLifeCycle = storageApi as StorageSdkLifecycle;
|
final storageLifeCycle = storageApi as StorageSdkLifecycle;
|
||||||
@@ -72,11 +76,15 @@ class LoginViewModel extends _$LoginViewModel {
|
|||||||
// 先完成 DB 操作,再标记登录状态(失败时不会误标为已登录)
|
// 先完成 DB 操作,再标记登录状态(失败时不会误标为已登录)
|
||||||
await storageLifeCycle.openDatabase(user.uid);
|
await storageLifeCycle.openDatabase(user.uid);
|
||||||
final userCompanion = UserDto.fromEntity(user).toCompanion();
|
final userCompanion = UserDto.fromEntity(user).toCompanion();
|
||||||
await storageApi.insert(userCompanion);
|
await storageApi.insertOrReplace(userCompanion);
|
||||||
|
|
||||||
// 全部成功后再更新登录状态,触发路由守卫重定向
|
// 全部成功后再更新登录状态,触发路由守卫重定向
|
||||||
|
// 注意:login() 触发导航后 provider 随即被 dispose,之后不能再写 state
|
||||||
|
if (!ref.mounted) return;
|
||||||
ref.read(authNotifierProvider).login();
|
ref.read(authNotifierProvider).login();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
// 导航已发生时 provider 已被 dispose,静默丢弃,不再写 state
|
||||||
|
if (!ref.mounted) return;
|
||||||
state = state.copyWith(error: e.toString(), isLoading: false);
|
state = state.copyWith(error: e.toString(), isLoading: false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -94,15 +102,19 @@ class LoginViewModel extends _$LoginViewModel {
|
|||||||
.read(loginUseCaseProvider)
|
.read(loginUseCaseProvider)
|
||||||
.execute(email: email, password: password);
|
.execute(email: email, password: password);
|
||||||
|
|
||||||
|
if (!ref.mounted) return;
|
||||||
state = state.copyWith(user: user, isLoading: false);
|
state = state.copyWith(user: user, isLoading: false);
|
||||||
} on FormatException catch (e) {
|
} on FormatException catch (e) {
|
||||||
// 格式校验失败(UseCase 层抛出)
|
// 格式校验失败(UseCase 层抛出)
|
||||||
|
if (!ref.mounted) return;
|
||||||
state = state.copyWith(error: e.message, isLoading: false);
|
state = state.copyWith(error: e.message, isLoading: false);
|
||||||
} on ApiError catch (e) {
|
} on ApiError catch (e) {
|
||||||
// 网络 / 服务端错误(Repository → SDK 透传)
|
// 网络 / 服务端错误(Repository → SDK 透传)
|
||||||
|
if (!ref.mounted) return;
|
||||||
state = state.copyWith(error: e.displayMessage, isLoading: false);
|
state = state.copyWith(error: e.displayMessage, isLoading: false);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// 兜底:防止未预期的异常导致 isLoading 死锁
|
// 兜底:防止未预期的异常导致 isLoading 死锁
|
||||||
|
if (!ref.mounted) return;
|
||||||
state = state.copyWith(error: e.toString(), isLoading: false);
|
state = state.copyWith(error: e.toString(), isLoading: false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,13 +15,12 @@ class LoginPage extends ConsumerWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
// ref.watch 保持 loginViewModelProvider 存活(AutoDispose 需要至少一个监听者)
|
||||||
|
final state = ref.watch(loginViewModelProvider);
|
||||||
final s = context.styles;
|
final s = context.styles;
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(title: const Text('登录'), automaticallyImplyLeading: false),
|
||||||
title: const Text('登录'),
|
|
||||||
automaticallyImplyLeading: false,
|
|
||||||
),
|
|
||||||
body: Center(
|
body: Center(
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
@@ -34,7 +33,9 @@ class LoginPage extends ConsumerWidget {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 32),
|
const SizedBox(height: 32),
|
||||||
FilledButton(
|
FilledButton(
|
||||||
onPressed: () => ref.read(loginViewModelProvider.notifier).demoLogin(),
|
onPressed: state.isLoading
|
||||||
|
? null
|
||||||
|
: () => ref.read(loginViewModelProvider.notifier).demoLogin(),
|
||||||
child: const Text('登录'),
|
child: const Text('登录'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
Reference in New Issue
Block a user