通过 SharedPrefs 帮助程序在活动之间使用数据



我有一个名为SessionManager的类,它应该使用SharedPrefs处理登录的会话。它在大多数情况下都有效。我遇到了一个问题,如果我注销(SharedPrefs 中没有任何内容)然后重新登录 - 那么数据就会null。但是,它不会null登录活动 - 但是当我离开登录活动转到主活动的那一刻,那就是它null的时候。显然,在活动之间使用 SharedPrefs 存在问题——但我不确定我是否理解为什么/如何。

另一件事 - 如果我关闭应用程序然后再次打开它 - SharedPref 数据在主活动中是正确的(因为我们在登录一次后从这里开始)。我上面描述的问题只发生在初始登录时。

为了简洁起见,我删除了 getter 方法,因为它们不是问题所在。

public class SessionManager {
    Context context;
    SharedPreferences pref;
    //Editor for Shared preferences
    SharedPreferences.Editor editor;
    //SharedPref file name
    private static final String PREF_NAME = "current.user";
    //All Shared Preferences Keys
    private static final String IS_LOGIN = "IsLoggedIn";
    //Username
    public static final String KEY_USERNAME = "username";
    //Name
    public static final String KEY_NAME = "name";
    //Email
    public static final String KEY_EMAIL = "email";
    //Constructor for SessionManager
    public SessionManager(Context context) {
        this.context = context;
        pref = this.context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
        editor = pref.edit();
    }
    /**
     * Create login session
     * @param username to store in SharedPrefs
     * @param email to store in SharedPrefs
     */
    public void createLoginSession(String username, String name, String email) {
        /*Store each value into SharedPrefs*/
        editor.putBoolean(IS_LOGIN, true);
        editor.putString(KEY_USERNAME, username);
        editor.putString(KEY_NAME, name);
        editor.putString(KEY_EMAIL, email);
        //Commit changes to SharedPrefs
        editor.commit();
    }
}

我通过这样做在任何活动中调用上述内容:

SessionManager mSession;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_welcome);
    ButterKnife.bind(this);
    mSession = new SessionManager(getApplicationContext());
}

我为每项活动都做上述操作。

我做错了什么?

编辑:这是我访问它和设置值的方式

在登录活动上访问它:

// Create a session with values from Firebase--logging shows me these values are correct
mSession.createLoginSession(USERNAME, NAME, EMAIL);
HashMap<String, String> user = mSession.getUserDetails();
String name = user.get(SessionManager.KEY_NAME);
String username = user.get(SessionManager.KEY_USERNAME);
String email = user.get(SessionManager.KEY_EMAIL);
// Logging shows me that the name, username, and email are set properly

然后使用该数据在 MainActivity 的导航抽屉中设置标题:

mSession = new SessionManager(getApplicationContext());
HashMap<String, String> user = mSession.getUserDetails();
String namey = user.get(SessionManager.KEY_NAME);
String emaily = user.get(SessionManager.KEY_EMAIL);
String usernamey = user.get(SessionManager.KEY_USERNAME);

我强烈考虑在这里使用单例模式。这样,您就可以保证在多个类中使用相同的实例。

不知道为什么这似乎是会话管理的首选实现。

示例用法

public class MainActivity extends AppCompatActivity {
    private SessionManager mSessionManager;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        this.mSessionManager = SessionManager.getInstance(getApplicationContext());
        mSessionManager.createLoginSession("tester", "Joe", "sample@example.com");
        boolean isLoggedIn = mSessionManager.getPref().getBoolean(SessionManager.IS_LOGIN, false);
        Log.d("MyTag", String.valueOf(isLoggedIn)); // true
        mSessionManager.logout();
        isLoggedIn = mSessionManager.getPref().getBoolean(SessionManager.IS_LOGIN, false);
        Log.d("MyTag", String.valueOf(isLoggedIn)); // false
    }
}

会话管理器类

public class SessionManager {
    private static SessionManager sInstance;
    private final SharedPreferences pref;
    private final SharedPreferences.Editor editor;
    public static final String PREF_NAME = "current.user";
    public static final String IS_LOGIN = "IsLoggedIn";
    public static final String KEY_USERNAME = "username";
    public static final String KEY_NAME = "name";
    public static final String KEY_EMAIL = "email";
    public static SessionManager getInstance(Context context) {
        if (sInstance == null) {
            sInstance = new SessionManager(context);
        }
        return sInstance;
    }
    private SessionManager(Context context) {
        pref = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
        editor = pref.edit();
    }
    public void createLoginSession(String username, String name, String email) {
        editor.putBoolean(IS_LOGIN, true);
        editor.putString(KEY_USERNAME, username);
        editor.putString(KEY_NAME, name);
        editor.putString(KEY_EMAIL, email);
        editor.commit();
    }
    public void logout() {
        editor.clear();
        editor.putBoolean(IS_LOGIN, false);
        editor.commit();
    }
    public String getLoggedInUsername() {
        String username = null;
        if (pref.contains(KEY_USERNAME) && pref.getBoolean(IS_LOGIN, false)) {
            username = pref.getString(KEY_USERNAME, null);
        }
        return username;
    }
    public SharedPreferences getPref() {
        return pref;
    }
}

我做错了什么?

我猜您在其他活动中使用了不同的上下文。您必须在任何地方使用相同的(getApplicagtionContext()很好),否则您的 SessionManager 将访问不同的共享首选项存储(如果您好奇:) XML 文件

最新更新