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

Android应用关闭后记住登录复选框失效及登出功能异常

记住登录功能异常排查与修复

现存问题

当前代码存在5处核心逻辑错误,和数据库无关,均为SharedPreferences使用与生命周期顺序问题:

  • 控件初始化顺序颠倒:执行「读取登录状态填充账号密码、勾选复选框」逻辑时,还未通过findViewById绑定输入框、复选框控件,此时控件引用为空,相关逻辑完全不生效,甚至可能触发空指针崩溃。
  • SharedPreferences多实例数据不互通:先后创建了两个独立的SharedPreferences文件:名为Data的文件用来读取ISLOGGEDIN登录标记,名为account的文件用来存储账号密码,两个文件数据完全隔离,读登录状态的位置根本拿不到存储的账号信息。
  • 数据未提交/逻辑写反:勾选「记住登录」分支中,对Data文件的editor存入ISLOGGEDIN=true后没有调用commit()/apply()提交,数据不会持久化到磁盘;未勾选「记住登录」的分支中,先写入登录标记再调用clear()清空所有数据,等于没有写入任何持久化信息,且该分支本就不该保存长期登录状态。
  • 自动跳转逻辑缺失:判断ISLOGGEDIN为true后,仅做了界面填充,没有编写跳转到HomeActivity的逻辑,就算登录状态读取正确,也会一直停留在登录页。
  • 登出逻辑不完整:当前登出代码仅做了页面跳转,没有清空持久化存储的登录状态标记,跳转后存储的登录信息依旧存在。

修复代码

1. 登录页onCreate逻辑修正

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // 第一步:先绑定所有控件,再做后续逻辑操作
    btnRegister = (Button) findViewById(R.id.buttonSignup);
    edtAccount = (EditText) findViewById(R.id.editTextAccount);
    edtPassword = (EditText) findViewById(R.id.editTextPassword);
    btnLogin = (Button) findViewById(R.id.buttonLogin);
    checkBoxRemember = (CheckBox) findViewById(R.id.checkBoxRemember);

    // 统一使用同一个SharedPreferences文件,不要创建多个实例
    SharedPreferences sharedPreferences = getSharedPreferences("user_config", MODE_PRIVATE);
    SharedPreferences.Editor editor = sharedPreferences.edit();

    // 读取登录状态,已登录直接跳转主页,不需要留在登录页
    boolean isLoggedIn = sharedPreferences.getBoolean("ISLOGGEDIN", false);
    if (isLoggedIn) {
        startActivity(new Intent(MainActivity.this, HomeActivity.class));
        finish();
        return;
    }

    db = new Database(this);

    btnRegister.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            startActivity(new Intent(MainActivity.this, RegisterActivity.class));
        }
    });

    btnLogin.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            String account = edtAccount.getText().toString().trim();
            String password = edtPassword.getText().toString().trim();

            if (account.isEmpty() || password.isEmpty()){
                Toast.makeText(MainActivity.this,
                        "Không được để trống tài khoản và mật khẩu",
                        Toast.LENGTH_SHORT).show();
                return;
            }

            Boolean loginResult = db.checkUserNamePassword(account, password);
            if (loginResult) {
                Intent intent = new Intent(MainActivity.this, HomeActivity.class);
                intent.putExtra("account", account);
                if (checkBoxRemember.isChecked()){
                    // 勾选记住登录:持久化存储登录标记、账号密码
                    editor.putBoolean("ISLOGGEDIN", true);
                    editor.putString("account", account);
                    editor.putString("password", password);
                    editor.apply();
                } else {
                    // 未勾选记住登录:清空之前的持久化登录信息,不存长期标记
                    editor.clear();
                    editor.apply();
                }
                startActivity(intent);
                finish();
            } else {
                Boolean userExist = db.checkUserName(account);
                if (userExist){
                    Toast.makeText(MainActivity.this,
                            "Sai mật khẩu!", Toast.LENGTH_SHORT).show();
                    edtPassword.setError("invalid password!");
                } else {
                    Toast.makeText(MainActivity.this,
                            "Account does not exist", Toast.LENGTH_SHORT).show();
                    edtAccount.setError("Tài khoản không tồn tại!");
                }
            }
        }
    });
}

2. 登出逻辑修正

登出时需要先清空持久化的登录状态,再跳转回登录页,同时清空任务栈防止返回键直接回到主页:

final AlertDialog.Builder builder = new AlertDialog.Builder(HomeActivity.this);
builder.setMessage(R.string.logout_message);
builder.setNegativeButton("Đăng xuất", new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialogInterface, int i) {
        // 清空登录状态
        SharedPreferences sharedPreferences = getSharedPreferences("user_config", MODE_PRIVATE);
        sharedPreferences.edit().clear().apply();
        
        // 跳转登录页并清空任务栈
        Intent intent = new Intent(HomeActivity.this, MainActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        startActivity(intent);
        finish();
    }
});
// 不要遗漏show方法,否则对话框不会弹出
builder.show();

内容的提问来源于stack exchange,提问作者Bùi Minh Thương

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 00:27:21