Files
Aq-Accounting-Flutter/lib/providers/session_provider.dart
T
2026-09-30 09:52:41 +08:00

38 lines
2.0 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'auth_provider.dart';
/// 当前登录用户的身份。`null` = 未登录;非 null(可能是空串)= 已登录。
///
/// ## 它是干什么的
///
/// **所有「属于某个用户」的 provider 都应该 watch 它。** 换了人(含登出)
/// 它们就会自动重建,上一个人的余额、预算、聊天记录不会留给下一个。
///
/// 为什么不能只靠 `autoDispose`:`ProviderContainer` 在 main.dart 里创建一次、
/// 进程存活期内不重建,所以**不带 autoDispose 的 provider 会活到 App 结束**,
/// 登出根本不会清它们。新用户登录后读到的还是缓存值,连请求都不发 ——
/// 表现就是「换了账号还看到上一个人的余额」。
///
/// ## 两个刻意的选择
///
/// **不直接 watch(authProvider),而是 select 出用户名。**
/// 改头像、改昵称也会换掉 `AuthState`。而依赖 `sessionUserProvider` 的
/// 那一批 provider 一旦被标记失效就会重建 —— 换个头像就把聊天记录、
/// 笔记列表、记账草稿全清一遍,明显不对。select 到用户名后,这些变化
/// 根本不会传导出去。
///
/// (细究的话 Riverpod 对 `==` 相等的值不会通知下游,所以「watch 整个
/// AuthState 但返回值仍是用户名」其实也不会误清。但那是靠值相等兜底,
/// 语义上等于承认「改头像也算换人」,不该赌这个 —— 直接 select 更明确。)
///
/// **用 isLoggedIn 判空,而不是只看 `user?.username`。**
/// `AuthNotifier.load()` 在「本地有 token 但拿不到 userInfo」时会得到
/// `AuthState(token: t, user: null)`。只看 username 会把这种情况误判成
/// 未登录,于是各处的空态护栏把整个 App 打回空数据。
final sessionUserProvider = Provider<String?>((ref) {
return ref.watch(authProvider.select(
(auth) => auth.isLoggedIn ? (auth.user?.username ?? '') : null,
));
});