You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 19:31:35