在安卓开发中,SharedPreferences 是一种轻量级的数据存储方式,适用于以键值对的形式保存少量数据。它通常用于存储应用的配置信息、用户偏好设置等简单数据,而不是处理大量数据或复杂数据结构的场景。SharedPreferences 的数据以 XML 文件的形式保存在设备的内部存储中,具体路径通常是 /data/data/<package_name>/shared_prefs/
目录下。
以下将结合使用场景、代码示例和详细讲解,帮助你全面理解 SharedPreferences 的用法。
使用场景
SharedPreferences 适用于以下几种常见的场景:
-
保存用户偏好设置
- 例如:用户选择的主题颜色(深色或浅色模式)、字体大小、是否开启推送通知等。
- 这些数据通常是用户个性化设置的一部分,数据量小且访问频繁。
-
保存应用状态
- 例如:记录用户上次的登录状态(如用户ID或是否已登录)、应用的版本号等。
- 这些信息需要在应用重启后快速恢复。
-
保存少量的配置信息
- 例如:API 密钥、服务器地址等静态配置。
- 这些数据通常在应用运行期间保持不变,且访问简单。
不适用的场景
- 大量数据存储:SharedPreferences 不是为大数据量设计的,过多数据会导致性能下降。
- 复杂数据结构:只支持基本数据类型(如
int
、boolean
、String
等)和Set<String>
,无法直接存储复杂对象。 - 需要事务支持:不支持事务操作,不适合需要数据一致性保证的场景。
基本使用方法
SharedPreferences 的使用主要包括以下步骤:
- 获取实例:通过
Context.getSharedPreferences()
获取 SharedPreferences 对象。 - 编辑数据:使用
SharedPreferences.Editor
接口修改数据。 - 保存数据:通过
Editor
的commit()
(同步)或apply()
(异步)方法保存。 - 读取数据:通过
get
方法(如getString()
、getBoolean()
)读取数据。
下面是一个具体的代码示例,展示如何使用 SharedPreferences 保存和读取用户的登录状态和用户名。
代码示例
以下是一个简单的安卓应用场景:用户输入用户名并点击登录按钮后,保存登录状态和用户名,并在下次启动应用时显示欢迎信息。
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
private EditText usernameEditText;
private Button loginButton;
private SharedPreferences sharedPreferences;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 初始化控件
usernameEditText = findViewById(R.id.usernameEditText);
loginButton = findViewById(R.id.loginButton);
// 获取 SharedPreferences 实例,文件名 "user_prefs",模式为私有
sharedPreferences = getSharedPreferences("user_prefs", Context.MODE_PRIVATE);
// 检查是否已登录
boolean isLoggedIn = sharedPreferences.getBoolean("is_logged_in", false);
if (isLoggedIn) {
String username = sharedPreferences.getString("username", "");
Toast.makeText(this, "欢迎回来," + username, Toast.LENGTH_SHORT).show();
}
// 设置登录按钮的点击事件
loginButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String username = usernameEditText.getText().toString();
if (!username.isEmpty()) {
// 获取 Editor 对象
SharedPreferences.Editor editor = sharedPreferences.edit();
// 保存用户名和登录状态
editor.putString("username", username);
editor.putBoolean("is_logged_in", true);
// 异步保存数据
editor.apply();
Toast.makeText(MainActivity.this, "登录成功", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(MainActivity.this, "请输入用户名", Toast.LENGTH_SHORT).show();
}
}
});
}
}
代码对应的布局文件(res/layout/activity_main.xml
)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<EditText
android:id="@+id/usernameEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入用户名" />
<Button
android:id="@+id/loginButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="登录" />
</LinearLayout>
代码详细解释
1. 获取 SharedPreferences 实例
sharedPreferences = getSharedPreferences("user_prefs", Context.MODE_PRIVATE);
- 参数1:
"user_prefs"
:指定 SharedPreferences 文件的名称,数据会保存到shared_prefs/user_prefs.xml
文件中。 - 参数2:
Context.MODE_PRIVATE
:表示该文件只能被当前应用访问,这是最常用的模式。
2. 读取数据
boolean isLoggedIn = sharedPreferences.getBoolean("is_logged_in", false);
String username = sharedPreferences.getString("username", "");
getBoolean(key, defaultValue)
:读取键"is_logged_in"
的布尔值,若不存在则返回默认值false
。getString(key, defaultValue)
:读取键"username"
的字符串,若不存在则返回空字符串""
。
3. 编辑数据
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("username", username);
editor.putBoolean("is_logged_in", true);
edit()
:返回一个Editor
对象,用于修改数据。putString()
和putBoolean()
:将键值对写入内存(尚未保存到文件)。
4. 保存数据
editor.apply();
apply()
:异步地将数据写入文件,不会阻塞主线程,适合大多数场景。- 替代方法
commit()
:同步保存,会阻塞主线程直到数据写入完成,返回布尔值表示是否成功。
高级用法
1. 默认 SharedPreferences
如果需要保存应用的全局偏好设置,可以使用:
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
这通常与 PreferenceFragmentCompat
配合使用,用于构建设置页面。
2. 监听数据变化
可以通过注册监听器来检测 SharedPreferences 的变化:
sharedPreferences.registerOnSharedPreferenceChangeListener(new SharedPreferences.OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
if (key.equals("username")) {
String newUsername = prefs.getString("username", "");
Toast.makeText(MainActivity.this, "用户名变为: " + newUsername, Toast.LENGTH_SHORT).show();
}
}
});
- 注意:在适当的时机(如
onDestroy()
)调用unregisterOnSharedPreferenceChangeListener()
以避免内存泄漏。
3. 清除数据
editor.clear()
:清除所有数据。editor.remove("key")
:移除指定键的数据。
示例:
editor.remove("username"); // 删除 username 键
editor.apply();
注意事项
-
性能
- SharedPreferences 在读取时会加载整个 XML 文件到内存,因此不适合存储大量数据。
-
线程安全
get
方法是线程安全的,但Editor
的put
方法不是,多线程操作时需同步处理。
-
支持的数据类型
- 仅支持基本类型(
boolean
、float
、int
、long
、String
)和Set<String>
。
- 仅支持基本类型(
-
安全性
- 数据以明文存储在 XML 文件中,不适合保存敏感信息(如密码、Token),建议使用加密存储或 Android KeyStore。
总结
SharedPreferences 是安卓开发中一种简单高效的存储方式,适合保存少量、结构简单的数据,如用户偏好、应用状态和少量配置信息。通过键值对的形式,开发者可以轻松实现数据的读写操作。结合上述代码示例和使用场景,SharedPreferences 在实际开发中非常实用,但需注意其性能和安全性限制,避免滥用。