Flutter实现跨天时清除SharedPreferences存储的PageView索引
解决方案:日期切换时重置PageView索引
核心逻辑
除了存储PageView的当前索引,额外存一份上次访问的日期。每次进入PageViewScreen时做两件事:
- 对比当前日期和存储的日期,要是跨天了就清除旧索引,重置为0,同时更新存储的日期
- 日期没变的话,直接读取之前存的索引恢复位置
修改后的Provider代码
import 'package:flutter/foundation.dart'; import 'package:shared_preferences/shared_preferences.dart'; class PageIndexProvider extends ChangeNotifier { int _currentIndex = 0; // 存储索引和日期的key final String _indexKey = 'page_view_index'; final String _dateKey = 'last_access_date'; int get currentIndex => _currentIndex; // 初始化:检查日期+加载索引 Future<void> init() async { final prefs = await SharedPreferences.getInstance(); final storedDate = prefs.getString(_dateKey); final today = _formatTodayDate(); // 跨天了,重置索引和日期 if (storedDate != today) { await prefs.setInt(_indexKey, 0); await prefs.setString(_dateKey, today); _currentIndex = 0; } else { // 同一天,读取存储的索引 _currentIndex = prefs.getInt(_indexKey) ?? 0; } notifyListeners(); } // 更新索引并持久化 Future<void> updateIndex(int newIndex) async { _currentIndex = newIndex; final prefs = await SharedPreferences.getInstance(); await prefs.setInt(_indexKey, newIndex); notifyListeners(); } // 把日期格式化为"年-月-日"字符串,忽略时分秒 String _formatTodayDate() { final now = DateTime.now(); return "${now.year}-${now.month.toString().padLeft(2, '0')}-${now.day.toString().padLeft(2, '0')}"; } }
修改后的PageViewScreen代码
import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; class PageViewScreen extends StatefulWidget { const PageViewScreen({super.key}); @override State<PageViewScreen> createState() => _PageViewScreenState(); } class _PageViewScreenState extends State<PageViewScreen> { late PageController _pageController; @override void initState() { super.initState(); // 页面构建完成后,触发Provider的初始化检查 WidgetsBinding.instance.addPostFrameCallback((_) { Provider.of<PageIndexProvider>(context, listen: false).init(); }); } @override void didChangeDependencies() { super.didChangeDependencies(); // 根据Provider的索引初始化PageController final provider = Provider.of<PageIndexProvider>(context); _pageController = PageController(initialPage: provider.currentIndex); } @override void dispose() { _pageController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( body: Consumer<PageIndexProvider>( builder: (context, provider, child) { return PageView( controller: _pageController, onPageChanged: (index) { // 滑动页面时更新索引 provider.updateIndex(index); }, children: const [ Center(child: Text("页面1")), Center(child: Text("页面2")), Center(child: Text("页面3")), ], ); }, ), ); } }
关键点说明
_formatTodayDate():只提取年、月、日组成字符串,确保只要日期变了(哪怕是凌晨0点过1秒)就会触发重置init()方法:放在Provider里统一处理日期检查和索引加载,逻辑更集中addPostFrameCallback:避免在initState里直接调用Provider方法时出现context未就绪的问题
内容的提问来源于stack exchange,提问作者Olamide Osuolale
相关产品推荐
相关产品推荐

