diff --git a/lib/controllers/load/locally.dart b/lib/controllers/load/locally.dart new file mode 100644 index 0000000..3c23795 --- /dev/null +++ b/lib/controllers/load/locally.dart @@ -0,0 +1,90 @@ +import 'dart:convert'; +import 'package:shared_preferences/shared_preferences.dart'; + +/// 时间: 2026-03-30 +/// 功能: 本地缓存管理器 +/// 介绍: 管理应用的本地缓存数据,包括排行榜数据等 +/// 最新变化: 新建本地缓存管理器 + +class LocalCacheManager { + static final LocalCacheManager _instance = LocalCacheManager._internal(); + factory LocalCacheManager() => _instance; + LocalCacheManager._internal(); + + static const String _preloadEnabledKey = 'preload_enabled'; + static const String _popularListCachePrefix = 'popular_list_cache_'; + + /// 获取预加载开关状态 + Future isPreloadEnabled() async { + final prefs = await SharedPreferences.getInstance(); + return prefs.getBool(_preloadEnabledKey) ?? true; + } + + /// 设置预加载开关状态 + Future setPreloadEnabled(bool enabled) async { + final prefs = await SharedPreferences.getInstance(); + await prefs.setBool(_preloadEnabledKey, enabled); + } + + /// 缓存排行榜数据 + Future cachePopularList( + String type, + List> data, + ) async { + final prefs = await SharedPreferences.getInstance(); + final key = _popularListCachePrefix + type; + final jsonData = jsonEncode(data); + await prefs.setString(key, jsonData); + + final timestampKey = '${key}_timestamp'; + await prefs.setInt(timestampKey, DateTime.now().millisecondsSinceEpoch); + } + + /// 获取缓存的排行榜数据 + Future>?> getCachedPopularList(String type) async { + final prefs = await SharedPreferences.getInstance(); + final key = _popularListCachePrefix + type; + final jsonData = prefs.getString(key); + + if (jsonData == null) { + return null; + } + + try { + final decoded = jsonDecode(jsonData); + if (decoded is List) { + return decoded.cast>(); + } + } catch (e) { + print('解析缓存数据失败: $e'); + } + + return null; + } + + /// 获取缓存时间戳 + Future getCacheTimestamp(String type) async { + final prefs = await SharedPreferences.getInstance(); + final key = '${_popularListCachePrefix}${type}_timestamp'; + return prefs.getInt(key); + } + + /// 清除指定类型的缓存 + Future clearCache(String type) async { + final prefs = await SharedPreferences.getInstance(); + final key = _popularListCachePrefix + type; + await prefs.remove(key); + await prefs.remove('${key}_timestamp'); + } + + /// 清除所有排行榜缓存 + Future clearAllPopularCache() async { + final prefs = await SharedPreferences.getInstance(); + final keys = prefs.getKeys(); + for (final key in keys) { + if (key.startsWith(_popularListCachePrefix)) { + await prefs.remove(key); + } + } + } +} diff --git a/lib/views/active/popular_page.dart b/lib/views/active/popular_page.dart index 487d092..4f51719 100644 --- a/lib/views/active/popular_page.dart +++ b/lib/views/active/popular_page.dart @@ -3,6 +3,7 @@ import '../../constants/app_constants.dart'; import '../../utils/responsive_layout.dart'; import '../../utils/http/http_client.dart'; import '../../models/poetry_model.dart'; +import '../../controllers/load/locally.dart'; /// 时间: 2026-03-25 /// 功能: 热门页面 @@ -130,7 +131,7 @@ class _PopularPageState extends State } return RefreshIndicator( - onRefresh: () async => await _loadRankList(), + onRefresh: () async => await _loadRankList(forceRefresh: true), child: NotificationListener( onNotification: (scrollNotification) { if (scrollNotification is ScrollEndNotification && @@ -318,7 +319,7 @@ class _PopularPageState extends State ); } - Future _loadRankList() async { + Future _loadRankList({bool forceRefresh = false}) async { setState(() { _loading = true; _errorMessage = ''; @@ -333,6 +334,26 @@ class _PopularPageState extends State ? 'day' : 'month'; + final isPreloadEnabled = await LocalCacheManager().isPreloadEnabled(); + + if (isPreloadEnabled && !forceRefresh) { + print('预加载模式:尝试从本地缓存加载数据'); + final cachedData = await LocalCacheManager().getCachedPopularList(type); + if (cachedData != null && cachedData.isNotEmpty) { + print('从本地缓存加载数据成功'); + if (mounted) { + setState(() { + _rankList = cachedData + .map((item) => PoetryModel.fromJson(item)) + .toList(); + _loading = false; + }); + } + return; + } + print('本地缓存为空,从服务器加载'); + } + print('正在请求排行榜数据: type=$type, period=$type'); final response = await HttpClient.get( @@ -349,6 +370,12 @@ class _PopularPageState extends State if (response.isSuccess && response.code == 0) { final data = response.data; final rankData = data['list'] as List? ?? []; + final rankDataList = rankData.cast>(); + + if (isPreloadEnabled) { + print('保存数据到本地缓存'); + await LocalCacheManager().cachePopularList(type, rankDataList); + } if (mounted) { setState(() { @@ -361,7 +388,9 @@ class _PopularPageState extends State } else { if (mounted) { setState(() { - _errorMessage = response.message ?? '获取排行榜失败'; + _errorMessage = response.message.isNotEmpty == true + ? response.message + : '获取排行榜失败'; _loading = false; }); } diff --git a/lib/views/home/home_page.dart b/lib/views/home/home_page.dart index cab7aab..4e2835c 100644 --- a/lib/views/home/home_page.dart +++ b/lib/views/home/home_page.dart @@ -191,7 +191,6 @@ class _HomePageState extends State } } } catch (e) { - debugPrint('加载诗词失败: $e'); if (mounted) { setState(() { _loading = false; @@ -269,7 +268,6 @@ class _HomePageState extends State } } } catch (e) { - debugPrint('加载指定诗词失败: $e'); if (mounted) { setState(() { _poetryData = _createDefaultPoetryData(); @@ -500,7 +498,7 @@ class _HomePageState extends State if (mounted) { PoetryStateManager.showSnackBar( context, - '加载下一条失败', + '加载下一条失败,建议开启离线模式', backgroundColor: AppConstants.errorColor, duration: const Duration(milliseconds: 200), ); diff --git a/lib/views/profile/settings/app_fun.dart b/lib/views/profile/settings/app_fun.dart index 945013d..6b0e038 100644 --- a/lib/views/profile/settings/app_fun.dart +++ b/lib/views/profile/settings/app_fun.dart @@ -3,6 +3,7 @@ import 'package:shared_preferences/shared_preferences.dart'; import '../../../constants/app_constants.dart'; import './widgets.dart'; import '../../home/home-load.dart'; +import '../../../controllers/load/locally.dart'; /// 时间: 2026-03-26 /// 功能: 功能设置页面 @@ -22,6 +23,7 @@ class _AppFunSettingsPageState extends State { bool _soundEnabled = true; bool _vibrationEnabled = true; bool _darkModeEnabled = false; + bool _preloadEnabled = true; bool _notificationEnabled = true; int _cacheSize = 128; @@ -40,6 +42,7 @@ class _AppFunSettingsPageState extends State { setState(() { _autoRefreshEnabled = prefs.getBool(_autoRefreshKey) ?? false; _debugInfoEnabled = prefs.getBool(_debugInfoKey) ?? false; + _preloadEnabled = prefs.getBool('preload_enabled') ?? true; }); } } @@ -66,6 +69,15 @@ class _AppFunSettingsPageState extends State { } } + Future _setPreload(bool value) async { + await LocalCacheManager().setPreloadEnabled(value); + if (mounted) { + setState(() { + _preloadEnabled = value; + }); + } + } + @override Widget build(BuildContext context) { return Scaffold( @@ -106,11 +118,12 @@ class _AppFunSettingsPageState extends State { ), _buildSwitchItem( '预加载', - '开启后优先使用本地缓存,\n减少与服务器的通信次数', - //关闭后,优先使用云端数据,无延迟,但刷新缓慢 - Icons.notifications_active, - _notificationEnabled, - (value) => setState(() => _notificationEnabled = value), + _preloadEnabled + ? '开启后 部分数据优先使用本地缓存,减少与服务器的通信次数' + : '关闭后,优先使用云端数据,无延迟,但刷新缓慢', + Icons.storage, + _preloadEnabled, + _setPreload, ), ]), const SizedBox(height: 16), diff --git a/lib/views/profile/settings/offline-data.dart b/lib/views/profile/settings/offline-data.dart index 3c26e3b..7360afe 100644 --- a/lib/views/profile/settings/offline-data.dart +++ b/lib/views/profile/settings/offline-data.dart @@ -445,7 +445,7 @@ class _OfflineDataPageState extends State { children: [ CircularProgressIndicator(), SizedBox(width: 16), - Text('正在获取服务器信息...'), + Text('正在检测网络状态...'), ], ), );