Flutter如何实现用户登录状态持久化 重启应用无需重复登录
解决方案
核心问题
你已经完成了登录成功后用户数据写入SharedPreferences的逻辑,缺失应用启动时登录状态校验步骤,所以重启应用后默认进入登录页,需要重新登录。
分步实现
1. 应用入口加登录状态判断
在main.dart中启动应用前先读取SharedPreferences中的登录凭证,存在有效凭证直接进入首页,否则进入登录页:
import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; void main() async { // 确保Flutter框架初始化完成,否则SharedPreferences调用会报错 WidgetsFlutterBinding.ensureInitialized(); SharedPreferences prefs = await SharedPreferences.getInstance(); // 读取存储的登录凭证,也可以读取你存的user字段判断 String? accessToken = prefs.getString('access_token'); // 根据凭证存在情况设置初始路由 runApp(MyApp( initialRoute: accessToken == null ? '/login' : '/home', )); } class MyApp extends StatelessWidget { final String initialRoute; const MyApp({super.key, required this.initialRoute}); @override Widget build(BuildContext context) { return MaterialApp( title: '登录状态保持演示', initialRoute: initialRoute, // 配置路由映射 routes: { '/login': (context) => const LoginPage(), '/home': (context) => const MyWidget(), }, ); } }
2. 补全主动注销逻辑
用户主动触发注销时,清空SharedPreferences存储的所有用户信息,跳转回登录页:
Future<void> logout(BuildContext context) async { SharedPreferences prefs = await SharedPreferences.getInstance(); // 清空所有缓存,也可以根据需求只删除指定字段 await prefs.clear(); // 清除路由栈,跳回登录页 if (context.mounted) { Navigator.pushNamedAndRemoveUntil(context, '/login', (route) => false); } }
3. 现有代码优化点
你现有代码存在两个可修复问题:
- 登录方法中的
String user = localStorage.getString('user');为冗余代码,无实际作用可直接删除 loginUser方法中异步请求的状态处理错误,加载弹窗未关闭、loading状态提前重置,修正后的代码如下:
void loginUser() async { if (_formKey.currentState!.validate()) { // 展示加载弹窗 showDialog( context: context, barrierDismissible: false, builder: (BuildContext context) { return const Center(child: CircularProgressIndicator()); }, ); setState(() => _isLoading = true); String email = _emailController.text; String password = _passwordController.text; try { User user = await authentication.login(email, password); if (user != null && context.mounted) { Navigator.push(context, MaterialPageRoute(builder: (context) => const MyWidget())); } } catch (error) { if (context.mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(error.toString())) ); } } finally { // 关闭加载弹窗,重置loading状态 if (context.mounted) { Navigator.pop(context); setState(() => _isLoading = false); } } } }
额外注意事项
如果你的服务端access_token有过期时间,后续请求接口时如果返回401未授权状态,也需要主动清空缓存跳转回登录页,避免出现已登录但请求失败的异常情况。
内容的提问来源于stack exchange,提问作者lucky
相关产品推荐
相关产品推荐

