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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.18 09:15:06