Android之SharedPreferences(SP)

打印 上一主题 下一主题

主题 1833|帖子 1833|积分 5499

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
SharedPreferences 是 Android 提供的一种轻量级的数据存储方式,重要用于存储简朴的键值对(key-value pairs)。它非常得当保存应用的设置信息、用户设置、应用状态等小型数据。
在 Android 中,SharedPreferences 默认情况下是进程内的,即每个进程都有自己独立的 SharedPreferences 实例
为了在多进程中可靠地共享数据,保举使用 ContentProvider。ContentProvider 是 Android 提供的用于进程间通信的机制,可以确保数据的同等性和同步性
MMKV——基于 mmap 的高性能通用 key-value 组件
概念



  • 键值对存储:SharedPreferences 使用键值对(key-value)的方式存储数据,键是字符串,值可以是多种根本数据类型。
  • 持久化存储:存储在 SharedPreferences 中的数据会被持久化到设备的文件体系中,纵然应用被关闭或设备重启,数据仍旧存在。
  • 轻量级:得当存储少量的简朴数据,不得当存储大量数据或复杂对象。
使用

1.获取 SharedPreferences 实例

可以通过以下几种方式获取 SharedPreferences 实例:
1.1 通过 Context 获取默认的 SharedPreferences 文件

  1. SharedPreferences sharedPreferences = getSharedPreferences("MyPrefs", Context.MODE_PRIVATE);
复制代码
1.2 通过 Activity 获取默认的 SharedPreferences 文件

  1. SharedPreferences sharedPreferences = getPreferences(Context.MODE_PRIVATE);
复制代码
1.3 通过 PreferenceManager 获取默认的 SharedPreferences 文件

  1. SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
复制代码
2.存储数据

使用 SharedPreferences.Editor 对象来存储数据。Editor 提供了多种 put 方法来存储不同类型的数据。
  1. SharedPreferences sharedPreferences = getSharedPreferences("MyPrefs", Context.MODE_PRIVATE);
  2. SharedPreferences.Editor editor = sharedPreferences.edit();editor.putString("username", "JohnDoe");editor.putInt("age", 30);editor.putBoolean("isLoggedIn", true);// 提交更改editor.apply(); // 大概使用 commit() 方法
复制代码


  • apply()异步提交,不会壅闭主线程,保举使用(没有返回值)。
  • commit()同步提交,返回一个布尔值表示提交是否成功(有返回值)。
3.读取数据

  1. SharedPreferences sharedPreferences = getSharedPreferences("MyPrefs", Context.MODE_PRIVATE);
  2. String username = sharedPreferences.getString("username", null);int age = sharedPreferences.getInt("age", 0);boolean isLoggedIn = sharedPreferences.getBoolean("isLoggedIn", false);
复制代码
4.删除数据

可以通过 Editor 的 remove 方法删除特定键的数据,大概使用 clear 方法删除全部数据。
  1. SharedPreferences sharedPreferences = getSharedPreferences("MyPrefs", Context.MODE_PRIVATE);
  2. SharedPreferences.Editor editor = sharedPreferences.edit();// 删除特定键的数据editor.remove("username");// 删除全部数据editor.clear();// 提交更改editor.apply(); // 大概使用 commit() 方法
复制代码
5.监听数据变革

可以通过 SharedPreferences.OnSharedPreferenceChangeListener 接口监听数据的变革。
  1. SharedPreferences sharedPreferences = getSharedPreferences("MyPrefs", Context.MODE_PRIVATE);
  2. SharedPreferences.OnSharedPreferenceChangeListener listener = new SharedPreferences.OnSharedPreferenceChangeListener() {    @Override    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {        // 当数据发生变革时的处理逻辑        if (key.equals("username")) {            String newUsername = sharedPreferences.getString(key, null);            // 处理新的用户名        }    }};// 注册监听器sharedPreferences.registerOnSharedPreferenceChangeListener(listener);// 取消注册监听器sharedPreferences.unregisterOnSharedPreferenceChangeListener(listener);
复制代码
使用场景



  • 用户设置:保存用户的偏好设置,如主题、通知设置等。
  • 应用状态:保存应用的状态信息,如上次登录时间、用户会话信息等。
  • 简朴数据缓存:保存一些简朴的临时数据,如搜索汗青、用户输入等。
注意事项



  • 实用范围:SharedPreferences 得当存储少量的简朴数据,不得当存储大量数据或复杂对象。
  • 线程安全:SharedPreferences 是线程安全的,可以在多个线程中安全地使用。
  • 性能:使用 apply() 方法举行异步提交,避免壅闭主线程。
SharedPreferences 为什么是线程安全的

SharedPreferences线程安全

SharedPreferences 的线程安全性重要体现在以下几个方面:
1. 数据存储和读取的线程安全性



  • 读取操作:SharedPreferences 的读取操作是线程安全的。读取数据时不会有并发问题,因为读取操作是无锁的,并且不会修改底层数据布局。
  • 写入操作:SharedPreferences 的写入操作通过 SharedPreferences.Editor 类举行。Editor 类使用内部锁机制来确保写入操作的原子性
2. 使用 apply() 方法举行异步提交



  • apply() 方法:apply() 方法在后台线程中异步提交数据,不会壅闭主线程。它通过 SharedPreferencesImpl 类的 enqueueDiskWrite 方法将写操作参加队列,并在后台线程中实验。这种方式避免了多个线程同时写入数据时的冲突
3. 使用 commit() 方法举行同步提交



  • commit() 方法:commit() 方法是同步提交数据,返回一个布尔值表示提交是否成功。它使用内部锁机制确保在提交过程中不会有其他线程举行写操作。虽然 commit() 是线程安全的,但它会壅闭调用它的线程,因此不保举在主线程中使用。
4. 数据监听的线程安全性



  • 数据监听:SharedPreferences 提供了 registerOnSharedPreferenceChangeListener 方法来注册数据变革监听器。当数据发生变革时,全部注册的监听器会被通知。SharedPreferences 内部通过同步机制确保在通知监听器时的线程安全性。
内部实现

SharedPreferences 的线程安全性重要通过以下几个内部实现来包管:


  • 锁机制:在写入操作中使用内部锁机制(如 synchronized 关键字)来确保写操作的原子性和线程安全性。
  • 异步处理:使用 apply() 方法举行异步提交,将写操作放入队列并在后台线程中实验,避免壅闭主线程。
  • 内存缓存:SharedPreferences 使用内存缓存来存储数据,淘汰频繁的 I/O 操作。读取操作直接从内存缓存中获取数据,包管了高效性和线程安全性。
以下是 SharedPreferences 内部使用锁机制确保线程安全性的简化示例:
  1. public final class SharedPreferencesImpl implements SharedPreferences {
  2.     private final Object mLock = new Object();
  3.     private final Map<String, Object> mMap;
  4.     @Override
  5.     public Map<String, ?> getAll() {
  6.         synchronized (mLock) {
  7.             return new HashMap<>(mMap);
  8.         }
  9.     }
  10.     @Override
  11.     public Editor edit() {
  12.         return new EditorImpl();
  13.     }
  14.     public final class EditorImpl implements Editor {
  15.         private final Map<String, Object> mModified;
  16.         @Override
  17.         public Editor putString(String key, String value) {
  18.             synchronized (mLock) {
  19.                 mModified.put(key, value);
  20.                 return this;
  21.             }
  22.         }
  23.         @Override
  24.         public void apply() {
  25.             final Runnable writeToDiskRunnable = new Runnable() {
  26.                 @Override
  27.                 public void run() {
  28.                     synchronized (mLock) {
  29.                         // 将 mModified 写入磁盘
  30.                     }
  31.                 }
  32.             };
  33.             // 异步执行写操作
  34.             new Thread(writeToDiskRunnable).start();
  35.         }
  36.         @Override
  37.         public boolean commit() {
  38.             synchronized (mLock) {
  39.                 // 将 mModified 写入磁盘
  40.                 return true;
  41.             }
  42.         }
  43.     }
  44. }
复制代码
在这个简化的示例中,mLock 用于同步访问共享资源(如 mMap 和 mModified),以确保线程安全性。
SharedPreferences 线程安全总结

SharedPreferences 的线程安全性是通过内部锁机制、异步处理和内存缓存等方式实现的。这些机制确保了在多线程环境下举行数据存储和读取操作时的安全性和高效性。
SharedPreferences 工具类示例

  1. import android.content.Context;
  2. import android.content.SharedPreferences;
  3. public class SharedPrefsHelper {
  4.     private static final String PREF_NAME = "MyPrefs";
  5.     private static SharedPrefsHelper instance;
  6.     private SharedPreferences sharedPreferences;
  7.     private SharedPreferences.Editor editor;
  8.     private SharedPrefsHelper(Context context) {
  9.         sharedPreferences = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
  10.         editor = sharedPreferences.edit();
  11.     }
  12.     public static synchronized SharedPrefsHelper getInstance(Context context) {
  13.         if (instance == null) {
  14.             instance = new SharedPrefsHelper(context.getApplicationContext());
  15.         }
  16.         return instance;
  17.     }
  18.     // 存储字符串
  19.     public void putString(String key, String value) {
  20.         editor.putString(key, value);
  21.         editor.apply();
  22.     }
  23.     // 读取字符串
  24.     public String getString(String key, String defaultValue) {
  25.         return sharedPreferences.getString(key, defaultValue);
  26.     }
  27.     // 存储整数
  28.     public void putInt(String key, int value) {
  29.         editor.putInt(key, value);
  30.         editor.apply();
  31.     }
  32.     // 读取整数
  33.     public int getInt(String key, int defaultValue) {
  34.         return sharedPreferences.getInt(key, defaultValue);
  35.     }
  36.     // 存储布尔值
  37.     public void putBoolean(String key, boolean value) {
  38.         editor.putBoolean(key, value);
  39.         editor.apply();
  40.     }
  41.     // 读取布尔值
  42.     public boolean getBoolean(String key, boolean defaultValue) {
  43.         return sharedPreferences.getBoolean(key, defaultValue);
  44.     }
  45.     // 存储浮点数
  46.     public void putFloat(String key, float value) {
  47.         editor.putFloat(key, value);
  48.         editor.apply();
  49.     }
  50.     // 读取浮点数
  51.     public float getFloat(String key, float defaultValue) {
  52.         return sharedPreferences.getFloat(key, defaultValue);
  53.     }
  54.     // 存储长整型
  55.     public void putLong(String key, long value) {
  56.         editor.putLong(key, value);
  57.         editor.apply();
  58.     }
  59.     // 读取长整型
  60.     public long getLong(String key, long defaultValue) {
  61.         return sharedPreferences.getLong(key, defaultValue);
  62.     }
  63.     // 删除特定键的数据
  64.     public void remove(String key) {
  65.         editor.remove(key);
  66.         editor.apply();
  67.     }
  68.     // 清除所有数据
  69.     public void clear() {
  70.         editor.clear();
  71.         editor.apply();
  72.     }
  73. }
复制代码
在应用中使用 SharedPrefsHelper 工具类举行数据存储和读取:
  1. public class MainActivity extends AppCompatActivity {
  2.     @Override
  3.     protected void onCreate(Bundle savedInstanceState) {
  4.         super.onCreate(savedInstanceState);
  5.         setContentView(R.layout.activity_main);
  6.         // 获取 SharedPrefsHelper 实例
  7.         SharedPrefsHelper sharedPrefsHelper = SharedPrefsHelper.getInstance(this);
  8.         // 存储数据
  9.         sharedPrefsHelper.putString("username", "Alan");
  10.         sharedPrefsHelper.putInt("age", 30);
  11.         sharedPrefsHelper.putBoolean("isLoggedIn", true);
  12.         // 读取数据
  13.         String username = sharedPrefsHelper.getString("username", "defaultName");
  14.         int age = sharedPrefsHelper.getInt("age", 0);
  15.         boolean isLoggedIn = sharedPrefsHelper.getBoolean("isLoggedIn", false);
  16.         // 显示读取的数据
  17.         Log.d("MainActivity", "Username: " + username);
  18.         Log.d("MainActivity", "Age: " + age);
  19.         Log.d("MainActivity", "Is Logged In: " + isLoggedIn);
  20.     }
  21. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

北冰洋以北

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表