目录
[🧠 1、创建一个最简单的demo](#🧠 1、创建一个最简单的demo)
[① 新建项目](#① 新建项目)
[② 修改布局文件------只放一个按钮(用于测试)](#② 修改布局文件——只放一个按钮(用于测试))
[③ 编写Java代码---MainAcitivity.java](#③ 编写Java代码—MainAcitivity.java)
[c:如何找到 SharedPreferences 生成的 XML 文件?](#c:如何找到 SharedPreferences 生成的 XML 文件?)
[🧠第二步:修改 布局文件](#🧠第二步:修改 布局文件)
🧠第三步:编写Java代码------MainActivity.java
🧠第五步:查看SharedPreferences自动生成的XML文件
🌟一、什么是SharedPreferences?
简单理解:
- SharedPreferences(简称SP)就是Android应用中用来保存少量配置数据的工具
- 就像你在电脑上用QQ**设置"是否允许陌生人添加好友"**下次打开时这个设置还在------这种"记住设置"的功能,就是靠SharedPreferences实现的!
- 你可以把他想象成一个小本子,用来记一些简单的信息,比如:用户名、密码、是否开启夜间模式、是否自动登陆
- ⚠️**注意:**SharedPreferences不适合存大量数据(如视频、图片),只适合存轻量级 的键值对数据(key-value)
🌟二、数据怎么存储
SharedPreference把数据保存为一个XML文件,放在手机的私有目录里:
/data/data/<你的应用包名>/shared_prefs/xxx.xml
比如:com.example.demo/shared_prefs/myshare.xml
这个文件只有你的APP能访问,别人看不到,很安全
🌟三、核心操作:读&写
| 操作 | 代码 | 说明 |
|---|---|---|
| 获取SharedPreferences(保存少量配置数据的工具) | getSharedPreferences("文件名",MODE_PRIVATE) | 文件名自定义,如config |
| 获取编辑器 | .edit() | 必须通过Editor才能写 |
| 写字符串 | editor.putString("key","value") | 键值对 |
| 写整数 | editor.putInt("key",123) | |
| 提交保存 | editor.apply() | 必须调用,否则不生效 |
| 读字符串 | sharedPreferences.getString("key","默认值") | 设置默认值是为了防止崩溃 |
| 读整数 | sharedPreferences.getInt("key:,0) | |
| [核心语句总结---基础] |
- 注意,写要有.apply(),读要有默认值
🧠 1、创建一个最简单的demo
① 新建项目
② 修改布局文件------只放一个按钮(用于测试)
XML
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<!--点击这个按钮,就执行"写入"或"读取"操作-->
<Button
android:id="@+id/buttonTest"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:backgroundTint="#FF9800"
android:text="点击测试"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
效果演示:

③ 编写Java代码---MainAcitivity.java
- 现在,我们只聚焦于SharedPreferences的读和写,其他功能先不管
a:写入操作:
java
package com.example.sharedprefsdemo;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
public class MainActivity extends AppCompatActivity {
//1、定义控件变量
private Button buttonTest;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_main);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
//2、找到按钮控件
buttonTest=findViewById(R.id.buttonTest);
//3、给按钮设置点击事件
buttonTest.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//点击按钮触发的效果就写在这里
//写入数据
/*
* getSharedPreferences("my_data",MODE_PRIVATE)以键值对的方式获取对象
* 文件名:my_data
* 模式:私有(只有本APP能访问)
* */
//① 获取SharedPreferences对象
SharedPreferences sharedPreferences = getSharedPreferences("my_data",MODE_PRIVATE);
//② 获取编辑器(Editor),准备写入
SharedPreferences.Editor editor = sharedPreferences.edit();
//③ 写入一个字符串:键是"name",值是"小明"
editor.putString("name","兔毛狸狸");
//④ 写入一个整数,键是"age",值是"20"
editor.putInt("age",20);
//⑤ 提交更改(保存到文件)
editor.apply();//异步保存,不卡界面
//⑥ 提示用户"已保存"
Toast.makeText(MainActivity.this, "数据已保存", Toast.LENGTH_SHORT).show();
}
});
}
}
关键代码截图:

b:运行效果
- 运行后,点击按钮 → 弹出"数据已保存!"
- → 此时,系统会在后台生成一个 XML 文件,存了
"name=小明"和"age=12"

c:如何找到 SharedPreferences 生成的 XML 文件?

导航到APP数据目录:data/data/com.example.sharedprefsdemo/shared_prefs/

a:读取操作(获取数据)
现在把上面的点击事件改成读取刚才保存的数据
修改Onclick方法
java
package com.example.sharedprefsdemo;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
public class MainActivity extends AppCompatActivity {
//1、定义控件变量
private Button buttonTest;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_main);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
//2、获取按钮控件
buttonTest=findViewById(R.id.buttonTest);
//3、触发按钮点击事件
buttonTest.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
/*
* 获取SharedPreferences里面的my_data文件
* 文件名:my_data
* 模型:私有,只有本APP开可以获取
* */
SharedPreferences sharedPreferences=getSharedPreferences("my_data",MODE_PRIVATE);
/*
* 读取字符串
* 键是name
*如果没有找到就返回默认值空字符 ""
* */
String name=sharedPreferences.getString("name","");
/*
* 读取整数
* 键是age
* 默认值是0
* */
int age=sharedPreferences.getInt("age",0);
//显示读取到的内容
Toast.makeText(MainActivity.this, "读取到:名字= "+name+",年龄= "+age, Toast.LENGTH_SHORT).show();
}
});
}
}
b:运行效果

🧭如何同时支持"写和读"
- 可以加一个计数器,第一个点击时写,第二次点是读
java
private int clickCount = 0; // 声明在类里(成员变量)
// 在 onClick 里:
clickCount++;
if (clickCount % 2 == 1) {
// 奇数次:写入
// ...(写入代码)
} else {
// 偶数次:读取
// ...(读取代码)
}
❓常见问题解答
Q:为什么我读不到数据?
A:检查三点:
- 文件名是否一致?(写和读必须用同一个名字,比如都是
"my_data")- 是否调用了
apply()或commit()?- 是否在写之后才读?(先保存,再读取)
Q:数据存在哪里?会丢失吗?
A:存在手机内部存储,只要你不卸载 App,数据就一直在。卸载就清空。
Q:能存很多数据吗?
A:不能!SharedPreferences 只适合少量简单配置(比如几十个键值对)。大量数据要用数据库(SQLite / Room)。
🌟实战:实现QQ登录页的"记住密码"功能
🧠功能描述
- 用户输入账号和密码
- 勾选"记住密码"------>下次打开APP时自动填充账号和密码
- 不勾选------>清空上次记录(下次登录需重新输入)
🧠第一步:理解实现逻辑

核心思想:启动时读------>登录时写
🧠第二步:修改 布局文件
XML
<CheckBox
android:id="@+id/checkBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="记住密码"
app:layout_constraintBottom_toTopOf="@+id/button"
app:layout_constraintEnd_toStartOf="@+id/textView2"
app:layout_constraintStart_toEndOf="@+id/textView"
app:layout_constraintTop_toBottomOf="@+id/editTextTextPassword" />
效果图:

🧠第三步:编写Java代码------MainActivity.java
java
package com.example.qqactivity;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.text.InputType;
import android.view.InputDevice;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
public class MainActivity extends AppCompatActivity {
//1、定义控件变量
private EditText editTextAccount;//账号输入框
private EditText editTextPassword;//密码输入款
private Button btnLogin;//登录按钮
private ImageView imageViewPasswordToggle;//
private boolean isPasswordVisible = false; // 密码可见性状态,默认为隐藏
private CheckBox checkBoxRemenbe;//"记住密码"复选框
private SharedPreferences sharedPreferences;//声明SharedPreferences对象,用于读写配置
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_main);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
/* 2、初始化SharedPreferences对象,
* login_prefs:文件名
* MODE_PRIVATE:模式为私有,只有本APP才能访问
*/
sharedPreferences=getSharedPreferences("login_prefs",MODE_PRIVATE);
/*
* 3、找到布局中所有的控件
* 函数initViews():用于找到所有的控件
*/
initViews();
/*
* 4、给按钮、眼睛、复选框等设置点击响应
* 方法satupClickListeners():用于实现点击响应
*/
satupClickListeners();
/*
* 5、启动时尝试加载上次保存的账号和密码
*/
loadSavedData();
}
//3 的方法实现:把JAVA变量和XML中的ID连起来
private void initViews(){
editTextAccount = findViewById(R.id.editTextTextPostalAddress2);
editTextPassword = findViewById(R.id.editTextTextPassword);
btnLogin = findViewById(R.id.button);
imageViewPasswordToggle = findViewById(R.id.imageView2); // 密码显示/隐藏切换按钮
checkBoxRemenbe=findViewById(R.id.checkBoxRemenber);
}
//4 的方法实现:设置所有的点击事件
private void satupClickListeners(){
/*
* ① 登录按钮点击事件
*/
btnLogin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
/*
* 获取用户输入的账号和密码
* trim()去掉首尾空格
*/
String account = editTextAccount.getText().toString().trim();
String password = editTextPassword.getText().toString().trim();
/*
* 校验:账号和密码不能为空
*/
if(account.isEmpty())
{
Toast.makeText(MainActivity.this,"请输入QQ号/手机号/邮箱",Toast.LENGTH_SHORT).show();
return;
}
if(password.isEmpty()){
Toast.makeText(MainActivity.this,"请输入密码",Toast.LENGTH_SHORT).show();
return;
}
/*
* ② 状态:获取"记住密码"是否被勾选
*/
boolean remenber = checkBoxRemenbe.isChecked();
/*
* ③ 获取编辑器,准备写入数据
*/
SharedPreferences.Editor editor = sharedPreferences.edit();
/*
* ④ 保存"是否记住密码"的状态
*/
editor.putBoolean("remember",remenber);
if(remenber)
{
//如果勾选了,就保存账号和密码
editor.putString("account",account);
editor.putString("password",password);
}
else
{
//如果没有勾选,就删除之前保存的账号和密码(防止残留)
editor.remove("account");
editor.remove("password");
}
/*
* ⑤ 提交更改
* apply():是异步保存,不卡主线程
*/
editor.apply();
/*
* ⑥ 提示登录成功
* 使用Toast弹窗
*/
Toast.makeText(MainActivity.this,"登录成功!账号:"+account,Toast.LENGTH_SHORT).show();
}
});
/*
* ⑦ 小眼睛图标点击事件:切换密码可见性
*/
imageViewPasswordToggle.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//调用切换方法
togglePasswordVisibility();
}
/*
* 实现切换密码显示/隐藏的方法
*/
private void togglePasswordVisibility(){
//取反,即点击眼睛图标,变为目前状态的反状态,即可见变不可见,不可见变可见
isPasswordVisible=!isPasswordVisible;
if(isPasswordVisible)
{
//设置明文密码
editTextPassword.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);
// 显示密码时显示show_password图标
imageViewPasswordToggle.setImageResource(R.mipmap.show_password);
}
else
{
//设置密码为不可见
editTextPassword.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
//隐藏密码时显示hide_password图标
imageViewPasswordToggle.setImageResource(R.mipmap.hide_password);
}
//把光标移到最后(避免切换时文字跳动)
editTextPassword.setSelection(editTextPassword.getText().length());
}
});
}
//5 的方法实现:启动时加载保存的数据
private void loadSavedData(){
//先读取,是否记住密码,默认是false
boolean remember=sharedPreferences.getBoolean("remember",false);
if(remember)
{
//如果记得,就读取账号和密码
String savedAccount = sharedPreferences.getString("account","");
String savedPassword = sharedPreferences.getString("password","");
//填入输入框
editTextAccount.setText(savedAccount);
editTextPassword.setText(savedPassword);
//勾选复选框
checkBoxRemenbe.setChecked(true);
}
//如果没记住,就什么都不做(保持空白,等待用户填入)
}
}
🧠第四步:查看启动效果

🧠第五步:查看SharedPreferences自动生成的XML文件

🧠第六步:总结
1、最终实现效果
| 操作 | 结果 |
|---|---|
| 首次打开 | 账号密码为空,复选框未勾选 |
| 输入账号密码+勾选+登录 | 数据保存 |
| 重启APP | 自动填入账号密码,复选框勾选 |
| 取消勾选+登录 | 清楚保存的数据 |
| 点击小眼睛 | 密码明文/密文切换 |
