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

Flutter中用SharedPreferences保存用户角色并按角色跳转页面

Flutter多角色登录状态持久化实现方案

1. 扩展SharedPreferences工具类(preference_helper.dart)

在原有登录状态存储基础上,新增用户角色的存储与读取方法:

import 'package:shared_preferences/shared_preferences.dart';

class PreferencesHelper {
  final Future<SharedPreferences> sharedPreferences;

  const PreferencesHelper({required this.sharedPreferences});

  static const String loginKey = 'LOGIN';
  static const String roleKey = 'USER_ROLE'; // 新增角色存储标识

  // 保存登录状态
  void setIsLogin(bool value) async {
    final prefs = await sharedPreferences;
    prefs.setBool(loginKey, value);
  }

  // 获取登录状态
  Future<bool> get isLogin async {
    final prefs = await sharedPreferences;
    return prefs.getBool(loginKey) ?? false;
  }

  // 新增:保存用户角色
  void setUserRole(String role) async {
    final prefs = await sharedPreferences;
    prefs.setString(roleKey, role);
  }

  // 新增:获取用户角色
  Future<String?> get userRole async {
    final prefs = await sharedPreferences;
    return prefs.getString(roleKey);
  }

  // 新增:清除登录状态与角色(退出登录时调用)
  void clearAuthData() async {
    final prefs = await sharedPreferences;
    prefs.remove(loginKey);
    prefs.remove(roleKey);
  }
}

2. 更新状态通知器(preference_notifier.dart)

同步扩展状态管理逻辑,增加角色状态的监听与更新:

import 'package:flutter/material.dart';
import 'preference_helper.dart';

class PreferencesNotifier extends ChangeNotifier {
  PreferencesHelper preferencesHelper;

  PreferencesNotifier({required this.preferencesHelper}) {
    _getAuthData(); // 替换原单一获取登录状态的方法,同时获取角色
  }

  bool _isLogin = false;
  bool get isLogin => _isLogin;

  String? _userRole;
  String? get userRole => _userRole;

  // 新增:同时获取登录状态和角色
  void _getAuthData() async {
    _isLogin = await preferencesHelper.isLogin;
    _userRole = await preferencesHelper.userRole;
    notifyListeners();

    debugPrint('登录状态: $_isLogin, 用户角色: $_userRole');
  }

  // 更新:设置登录状态时可同步保存角色
  void setAuthState(bool isLogin, [String? role]) async {
    await preferencesHelper.setIsLogin(isLogin);
    if (role != null) {
      await preferencesHelper.setUserRole(role);
    }
    _getAuthData(); // 重新拉取数据并更新状态
  }

  // 新增:退出登录时清除存储数据
  void logout() async {
    await preferencesHelper.clearAuthData();
    _getAuthData();
  }
}

3. 修改登录页面逻辑

登录成功后从Firestore获取角色,保存到SharedPreferences并直接跳转对应页面:

MaterialButton(
  color: primaryColor,
  textTheme: ButtonTextTheme.primary,
  height: 40,
  shape: RoundedRectangleBorder(
    borderRadius: BorderRadius.circular(16),
  ),
  onPressed: () async {
    setState(() {
      _isLoading = true;
    });

    try {
      final navigator = Navigator.of(context);
      final email = _emailController.text;
      final password = _passwordController.text;

      // 完成Firebase登录验证
      await _auth.signInWithEmailAndPassword(
        email: email,
        password: password,
      );

      User? user = FirebaseAuth.instance.currentUser;
      if (user != null) {
        // 从Firestore获取用户角色
        DocumentSnapshot userDoc = await FirebaseFirestore.instance
            .collection('users')
            .doc(user.uid)
            .get();
        
        if (userDoc.exists) {
          String role = userDoc.get('role');
          // 保存登录状态和角色到本地
          value.setAuthState(true, role);

          // 根据角色跳转对应首页
          if (role == "user") {
            navigator.pushReplacementNamed(UserHomePage.routeName);
          } else {
            navigator.pushReplacementNamed(AdminHomePage.routeName);
          }
        } else {
          debugPrint('用户数据不存在');
        }
      }
    } catch (err) {
      final snackBar = SnackBar(content: Text(err.toString()));
      ScaffoldMessenger.of(context).showSnackBar(snackBar);
    } finally {
      setState(() {
        _isLoading = false;
      });
    }
  },
  child: const Text('Login'),
),

注意:移除原登录逻辑中的route()和navigator.pushReplacementNamed(HomePage.routeName),避免重复跳转冲突。

4. 调整APP启动路由(main.dart)

启动时直接根据本地存储的角色跳转对应页面:

// 初始化PreferencesHelper
final preferencesHelper = PreferencesHelper(
  sharedPreferences: SharedPreferences.getInstance(),
);

// 获取本地存储的登录状态和角色
bool isLoggedIn = await preferencesHelper.isLogin;
String? userRole = await preferencesHelper.userRole;

// 确定初始路由
String initialRoute = LoginPage.routeName;
if (isLoggedIn) {
  initialRoute = userRole == "user" 
      ? UserHomePage.routeName 
      : AdminHomePage.routeName;
}

runApp(
  MyApp(
    pageRouteName: initialRoute,
  ),
);

5. 退出登录逻辑补充(可选)

在退出按钮中调用清除方法,同步本地存储和Firebase状态:

TextButton(
  onPressed: () async {
    await FirebaseAuth.instance.signOut();
    Provider.of<PreferencesNotifier>(context, listen: false).logout();
    Navigator.pushReplacementNamed(context, LoginPage.routeName);
  },
  child: const Text('退出登录'),
)

内容的提问来源于stack exchange,提问作者Akhmad Kurniawan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 04:50:23