如何在Flutter中用SharedPreferences实现引导页仅显示一次且非首页
实现方案
核心逻辑是:在应用的实际首页启动时,先读取SharedPreferences的标记,判断是否需要跳转引导页,而非把引导页设为入口页。
步骤1:封装SharedPreferences工具方法(可选,简化代码)
import 'package:shared_preferences/shared_preferences.dart'; class Prefs { // 读取是否已看过引导页的标记 static Future<bool> hasSeenOnboarding() async { final prefs = await SharedPreferences.getInstance(); return prefs.getBool('hasSeenOnboarding') ?? false; } // 标记引导页已查看 static Future<void> markOnboardingSeen() async { final prefs = await SharedPreferences.getInstance(); await prefs.setBool('hasSeenOnboarding', true); } }
步骤2:在实际首页中处理跳转逻辑
假设你的应用实际首页是HomeScreen,可以通过两种方式实现跳转判断:
方式一:在首页初始化时检查跳转
class HomeScreen extends StatefulWidget { const HomeScreen({super.key}); @override State<HomeScreen> createState() => _HomeScreenState(); } class _HomeScreenState extends State<HomeScreen> { @override void initState() { super.initState(); _checkAndNavigateToOnboarding(); } Future<void> _checkAndNavigateToOnboarding() async { final hasSeen = await Prefs.hasSeenOnboarding(); if (!hasSeen) { // 使用pushReplacement,避免用户返回时再次进入引导页 await Navigator.pushReplacement( context, MaterialPageRoute(builder: (context) => const OnboardingScreen()), ); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('应用首页')), body: const Center(child: Text('应用主内容区域')), ); } }
方式二:用FutureBuilder处理加载过渡(更流畅)
如果不想让首页闪一下再跳转,可以用FutureBuilder在加载时显示过渡页面:
class HomeWrapper extends StatelessWidget { const HomeWrapper({super.key}); @override Widget build(BuildContext context) { return FutureBuilder<bool>( future: Prefs.hasSeenOnboarding(), initialData: false, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { // 加载中显示闪屏或加载动画 return const Scaffold(body: Center(child: CircularProgressIndicator())); } final hasSeen = snapshot.data ?? false; return hasSeen ? const HomeScreen() : const OnboardingScreen(); }, ); } }
之后把MaterialApp的home属性设为HomeWrapper即可。
步骤3:引导页中标记已查看
在引导页的完成按钮点击事件里,标记引导页已查看并返回首页:
class OnboardingScreen extends StatelessWidget { const OnboardingScreen({super.key}); @override Widget build(BuildContext context) { return Scaffold( body: Center( child: ElevatedButton( onPressed: () async { await Prefs.markOnboardingSeen(); // 替换当前路由,返回首页 Navigator.pushReplacement( context, MaterialPageRoute(builder: (context) => const HomeScreen()), ); }, child: const Text('完成引导,进入首页'), ), ), ); } }
关键注意事项
- 跳转时必须用
pushReplacement,避免用户按返回键回到引导页。 - SharedPreferences操作是异步的,不要在build方法中直接调用,避免阻塞UI。
- 测试时如果需要重置引导页状态,可以调用
prefs.remove('hasSeenOnboarding')清除标记。
内容的提问来源于stack exchange,提问作者Mahmoud Erfan
相关产品推荐
相关产品推荐

