// notices_provider.dart — 系统通知状态装配:复用 apiClientProvider,未登录不打网络。 // // 对照 invite_provider.dart(装配模式:未登录 build 返回 null、不打网络)与 // update_provider.dart(延迟首拉的可取消 Timer 模式)。回前台重拉由 Task 10 的 // 消费方(WidgetsBindingObserver)调用 refresh(),本 provider 只暴露 refresh()。 import 'dart:async'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../services/notices_api.dart'; import 'account_providers.dart'; import 'auth_provider.dart'; /// 首次拉取前的延迟(避开登录/首屏竞争)。 const _kInitialDelay = Duration(seconds: 2); final noticesApiProvider = Provider((ref) => NoticesApi(ref.watch(apiClientProvider))); class NoticesNotifier extends AsyncNotifier { Timer? _initialTimer; @override Future build() async { ref.onDispose(() => _initialTimer?.cancel()); // 未登录返回 null(不打网络)。 final token = ref.watch(authProvider).accessToken; if (token == null || token.isEmpty) return null; // 延迟首拉:用可取消的 Timer(而非 Future.delayed,其内部 timer 无法取消, // provider 在延迟期间被 dispose 时会悬挂)。 final ready = Completer(); _initialTimer = Timer(_kInitialDelay, ready.complete); await ready.future; // 若延迟期间被 dispose,_initialTimer 取消 → 永不 complete,build 中止 return ref.read(noticesApiProvider).fetch(); } Future refresh() async { state = const AsyncLoading(); state = await AsyncValue.guard(() => ref.read(noticesApiProvider).fetch()); } /// 标记全部已读:调服务端成功后,本地把 unreadCount 置 0、items 的 unread 置 false。 Future markAllRead() async { final current = state.value; if (current == null) return; await ref.read(noticesApiProvider).markRead(); state = AsyncValue.data(current.copyWith( items: current.items.map((n) => n.copyWith(unread: false)).toList(), unreadCount: 0, )); } } final noticesProvider = AsyncNotifierProvider(NoticesNotifier.new);