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

如何使用Shared Preferences存储字符串类型用户名数据

Android SharedPreferences 实现用户名持久化与全局调用方案

SharedPreferences是Android系统自带的轻量级键值对存储,专门用来存用户名、配置开关这类小体量基础数据,存储在应用私有目录,默认仅当前应用可访问,不需要引入额外第三方依赖。

1 封装全局SP工具类

不要在每个业务页面重复写SP实例获取、编辑提交的模板代码,抽成单例工具类统一维护,避免重复代码和存储逻辑混乱。

import android.content.Context
import android.content.SharedPreferences

class SpUtils private constructor(context: Context) {
    private val sp: SharedPreferences = context.applicationContext.getSharedPreferences(
        "app_local_config",
        Context.MODE_PRIVATE
    )

    // 存储字符串类型数据
    fun putString(key: String, value: String) {
        sp.edit().putString(key, value).apply()
    }

    // 读取字符串类型数据,默认返回空字符串
    fun getString(key: String, defaultValue: String = ""): String {
        return sp.getString(key, defaultValue) ?: defaultValue
    }

    // 删除指定key对应的数据
    fun remove(key: String) {
        sp.edit().remove(key).apply()
    }

    // 清空全部本地SP数据
    fun clearAll() {
        sp.edit().clear().apply()
    }

    companion object {
        @Volatile
        private var instance: SpUtils? = null

        fun getInstance(context: Context): SpUtils {
            return instance ?: synchronized(this) {
                instance ?: SpUtils(context).also { instance = it }
            }
        }
    }
}

如果想省掉每次传Context的步骤,可以在自定义Application中提前初始化实例:

class MyApp : Application() {
    companion object {
        lateinit var sp: SpUtils
            private set
    }

    override fun onCreate() {
        super.onCreate()
        sp = SpUtils.getInstance(this)
    }
}

记得在AndroidManifest.xml的<application>标签下配置android:name=".MyApp",否则自定义Application不会生效。

2 登录成功后写入用户名

在登录接口请求成功、拿到服务端返回的用户名后,直接调用工具类写入即可:

loginConfirmBtn.setOnClickListener {
    val inputAccount = accountInput.text.toString().trim()
    val inputPwd = pwdInput.text.toString().trim()
    // 替换为你自己的登录请求逻辑
    loginViewModel.doLogin(inputAccount, inputPwd) { success, username ->
        if (success) {
            // 写入用户名到本地
            if (::sp.isInitialized) {
                sp.putString("current_login_username", username)
            } else {
                SpUtils.getInstance(this@LoginActivity).putString("current_login_username", username)
            }
            // 跳转首页、关闭登录页
            startActivity(Intent(this@LoginActivity, MainActivity::class.java))
            finish()
        } else {
            Toast.makeText(this@LoginActivity, "账号或密码错误", Toast.LENGTH_SHORT).show()
        }
    }
}

3 全局任意位置读取数据

只要是在应用进程内,不管是Activity、Fragment、自定义View还是其他业务类,都可以直接读取存储的用户名,不需要页面间层层传值:

// 首页设置欢迎语示例
val currentUsername = if (::sp.isInitialized) {
    sp.getString("current_login_username")
} else {
    SpUtils.getInstance(this).getString("current_login_username")
}
welcomeText.text = "你好,$currentUsername"

退出登录时记得调用sp.remove("current_login_username")清除本地存的用户信息,避免多账号登录时数据串号。

注意事项

  • 仅用SharedPreferences存储小体量数据,不要存长JSON、大段文本、图片Base64等内容,这类大体积数据用Room数据库或文件存储更合适
  • 永远使用MODE_PRIVATE模式创建SP实例,其余公开访问模式已在高版本Android废弃,存在数据泄露风险
  • 用户名这类非敏感数据可以明文存储,若要存token、密码这类敏感信息,建议先做加密再写入
  • 写入操作优先用apply(),异步落盘不会阻塞主线程;只有需要同步确认写入结果的场景才用commit(),避免主线程卡帧
  • 工具类内部已经转用ApplicationContext存储SP实例,不会持有Activity/Fragment的Context引用,不用担心内存泄漏问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 08:54:20