如何使用SharedPreferences控制Flutter应用的初始路由?
你可以通过两种实用方式实现需求:在应用启动前异步获取登录状态,或者用FutureBuilder在页面构建时动态处理状态,具体实现如下:
方法一:在main函数中提前获取状态(推荐)
这种方式会在应用启动前先拿到登录状态,直接传递给根组件设置初始路由,逻辑简洁直接:
import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; void main() async { // 必须调用此方法,确保Flutter初始化完成后再执行异步操作 WidgetsFlutterBinding.ensureInitialized(); // 获取SharedPreferences实例并读取登录状态 final SharedPreferences prefs = await SharedPreferences.getInstance(); bool isLoggedIn = prefs.getBool('loggedIn') ?? false; // 首次打开默认未登录 runApp(MyApp(isLoggedIn: isLoggedIn)); } class MyApp extends StatelessWidget { final bool isLoggedIn; const MyApp({super.key, required this.isLoggedIn}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Demo App', // 根据登录状态设置初始路由 initialRoute: isLoggedIn ? '/home' : '/login', routes: { '/login': (context) => const LoginPage(), '/home': (context) => const HomePage(), }, ); } } // 示例登录页面 class LoginPage extends StatelessWidget { const LoginPage({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('登录')), body: Center( child: ElevatedButton( onPressed: () async { // 执行登录逻辑后保存状态 final SharedPreferences prefs = await SharedPreferences.getInstance(); await prefs.setBool('loggedIn', true); // 登录成功后替换路由,避免返回登录页 if (!context.mounted) return; Navigator.pushReplacementNamed(context, '/home'); }, child: const Text('登录'), ), ), ); } } // 示例首页 class HomePage extends StatelessWidget { const HomePage({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('首页')), body: const Center(child: Text('已登录,欢迎使用')), ); } }
方法二:用FutureBuilder处理异步状态
如果不想把异步逻辑放在main函数里,可以用FutureBuilder在根组件中动态判断页面,还能处理加载状态:
import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); // 封装获取登录状态的异步方法 Future<bool> _getLoginStatus() async { final SharedPreferences prefs = await SharedPreferences.getInstance(); return prefs.getBool('loggedIn') ?? false; } @override Widget build(BuildContext context) { return MaterialApp( title: 'Demo App', home: FutureBuilder<bool>( future: _getLoginStatus(), builder: (context, snapshot) { // 状态未返回时显示加载动画 if (snapshot.connectionState == ConnectionState.waiting) { return const Scaffold(body: Center(child: CircularProgressIndicator())); } // 根据状态渲染对应页面 bool isLoggedIn = snapshot.data ?? false; return isLoggedIn ? const HomePage() : const LoginPage(); }, ), routes: { '/login': (context) => const LoginPage(), '/home': (context) => const HomePage(), }, ); } } // LoginPage和HomePage代码同方法一,此处省略
注意事项
- 必须在main函数的异步操作前调用
WidgetsFlutterBinding.ensureInitialized(),否则会因Flutter未初始化完成报错。 - 用
?? false处理loggedIn字段不存在的场景(比如用户首次打开应用),确保默认状态为未登录。 - 登录成功后使用
pushReplacementNamed替换路由,而不是普通的push,这样用户点击返回按钮不会回到登录页。
内容的提问来源于stack exchange,提问作者user15723984
相关产品推荐
相关产品推荐

