SharedPreferences

QuibblerQuibbler 2020-10-03 约 13 分钟 1763 次阅读

SharedPreferences

应用开发中常常需要保存一些简单的状态,比如时间、开关状态等,使用数据库有点大材小用,Android系统有专门的数据结构用来保存简单的数据:SharedPreferences。通常配合设置界面保存各种设置项状态,详见《PreferenceScreen 设置项》及《PreferenceFragmentCompat 设置界面》。

1、SharedPreferences

SharedPreferences是轻量级的存储类,主要是保存一些小的数据,一些状态信息。

1.1、SharedPreferences介绍

从API Level 1就提供的系统工具。提供了很多简单易用的API,方便开发者调用读写数据。但是!SharedPreferences为了保证全局读写的唯一性,即有可能阻塞主线程早ANR。这种情况线上遇到的太多了。

1.2、SharedPreferences读写模式

SharedPreferences有四种MODE可选,

①MODE_PRIVATE:只能被自己的应用访问,是默认的MODE,推荐!

②MODE_WORLD_READABLE:可以被其它应用读取

③MODE_WORLD_WRITEABLE:可以被其它应用读写

④MODE_MULTI_PROCESS:提供跨进程访问的功能

定义的源码如下:

/** @hide */
    @IntDef(flag = true, prefix = { "MODE_" }, value = {
            MODE_PRIVATE,
            MODE_WORLD_READABLE,
            MODE_WORLD_WRITEABLE,
            MODE_MULTI_PROCESS,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface PreferencesMode {}

2、获取SharedPreferences

目前有三种途径获取SharedPreferences对象。

2.1、通过Context

Context提供了操作SharedPreferences的三个方法

①创建指定名称的SP

//指定名称,保存成name.xml中
    getSharedPreferences("name", Context.MODE_PRIVATE);

②删除指定名称的SP

boolean deleteSharedPreferences(String name)

③SP迁移,数据从原Context上下文迁移到调用上下文Context中

boolean moveSharedPreferencesFrom(Context sourceContext, String name)

2.2、通过Activity()(不推荐)

在Activity可以发现多一个方法getPreferences(int mode),只需要指定读写mode即可

//默认当前Activity名
    getPreferences(Context.MODE_PRIVATE);

查看源码可以看见,默认了SP名为当前Activity类名。

public SharedPreferences getPreferences(@Context.PreferencesMode int mode) {
        return getSharedPreferences(getLocalClassName(), mode);
    }

因为Activity继承自Context所以Context中的方法都可以使用。

2.3、通过PreferenceManager(不推荐)

①获取默认的SharedPreference

//deprecated,不推荐
    PreferenceManager.getDefaultSharedPreferences(this);

查看PreferenceManager源码:

public static SharedPreferences getDefaultSharedPreferences(Context context) {
        return context.getSharedPreferences(getDefaultSharedPreferencesName(context),
                getDefaultSharedPreferencesMode());
    }
    //获取默认MODE,就是MODE_PRIVATE
    private static int getDefaultSharedPreferencesMode() {
        return Context.MODE_PRIVATE;
    }
    //默认SP名就是:包名_preferences
    public static String getDefaultSharedPreferencesName(Context context) {
        return context.getPackageName() + "_preferences";
    }

②获取默认SP名就是:包名_preferences

//获取当前SharedPreference的XML文件名称
    PreferenceManager.getDefaultSharedPreferencesName(this);

3、读写操作

SP提供了简单的API读写数据。

3.1、读

从SharedPreferences直接读数据,有如下一些方法:

①Map<String, ?> getAll()

②boolean getBoolean(String key, boolean defValue)

③float getFloat(String key, float defValue)

④long getLong(String key, long defValue)

⑤String getString(String key, @Nullable String defValue)

⑥Set<String> getStringSet(String key, @Nullable Set<String> defValues)

例:

sharedPreferences.getString("name", "Quibbler");
    sharedPreferences.getInt("age", 26);
    sharedPreferences.getBoolean("is", false);

3.2、写

写数据到SharedPreferences需要借助SharedPreference.Editor,而且方法都会返回当前Editor,方便使用链式调用一次写完。关于apple()和commit()的详细区别详见《源码理解apply()与commit()的区别》。

①Editor putString(String key, @Nullable String value)

②Editor putStringSet(String key, @Nullable Set<String> values)

③Editor putInt(String key, int value)

④Editor putLong(String key, long value)

⑤Editor putFloat(String key, float value)

⑥Editor putBoolean(String key, boolean value)

⑦Editor remove(String key):移除指定key对应的值

⑧Editor clear():清空数据

⑨boolean commit():立即提交数据到存储

⑩void apply():先写入内容,最后写到磁盘

例:

SharedPreferences.Editor editor = sharedPreferences.edit();
    editor.putBoolean("is", true);
    editor.putString("name", "QUIBBLER");
    editor.putInt("age", 25);
    editor.apply();  //异步先提交到内存中
    //或者
    editor.commit(); //同步写到存储,耗时

4、监听

查看源码的时候发了还有监听SharedPreferences变化的监听器接口OnSharedPreferenceChangeListener

public interface OnSharedPreferenceChangeListener {
        /**
         * 更改,添加或删除共享首选项时调用。 
         * 即使将首选项设置为其现有值,也可以调用此方法。
         * 该回调将在主线程上运行。
         *
         * @param sharedPreferences The {@link SharedPreferences} that received the change.
         * @param key 已更改,添加或删除的首选项的键。 
         */
        void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key);
    }

并且提供了注册和反注册监听器的方法:

①registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener)

②unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener)

注意:SharedPreferences当前不存储对侦听器的强引用。您必须存储对侦听器的强引用,否则将容易受到垃圾回收的影响。我们建议您在需要侦听器的对象的实例数据中保留对侦听器的引用。

5、注意

SharedPreferences及时读写操作到放到子线程,及时使用apply()异步提交,即使不大量的写入数据也会出问题,可能阻塞主线程,严重的时候会导致ANR。

①即使在子线程读写,当Activity opPause等情况发生时,会强制写入全部数据任务。如果apply()提交到任务队列的任务过多,主线程会阻塞等待。

②即使每次只修改一个key,也会写一遍全部的文件。所以SP文件一定不能太大,保存很多key,一般50个都已经很多了!

③不要想着使用SP跨进程保存一些状态给其它进程读!

相关资料:

         Docs > Reference > SharedPreferences">Android Developers > Docs > Reference > SharedPreferences

        Data-storage pref

        Save key-value data

        Android SharedPreferences使用以及原理详解

        Android之SharedPreferences简介及使用说明

        SharedPreference的工具类

相关推荐

精选
ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager
Android

ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager

ViewPager1、ViewPagerandroidx.viewpager.widget.ViewPager,Android中使用非常广泛的控件,可以说是APP必备:首次打开引导页、页面Banner广告等。常用方法:setAdapter() 设置适配器setOffscreenPageLimit() 设置缓存的页面个数,默认是 1setCurrentItem() 跳转到特定的页面setOnPage

1.1k
获取Android内置WebView内核版本
Android

获取Android内置WebView内核版本

获取Android内置WebView内核版本竟然能遇到这样奇葩的事情,网页用的技术过于新颖,以至于只支持高版本Chromium内核的,低版本安卓系统中内置的内核版本较低,无法加载前端页面。1、设置查看在系统设置里 > 应用 > 应用管理 > 显示系统应用,查看WebView组件:2、页面查看通过WebView发起的网络请求,都会带上浏览器的UA,通常页面都可以通过UA判断浏览器的内核版本。这里有两

1.1w
Android 14适配总结
Android

Android 14适配总结

Android 14适配总结毕业工作至今已经适配了三个Android大版本,从Android 11到Android 12、再到Android 13。2023年,Google即将推出的Android 14,上半年已经开始第一批适配。现在,第四个Android版本已经适配完,总结记录一下。1、Android 14计划Google一般会在2月份对外发布预告,同时放出开发者预览版。“拉通”各大平台、厂商以

1.1w