[技术博客] 利用SharedPreferences来实现登录状态的记忆功能

一、SharedPreferences简介

SharedPreferences是Android平台上一个轻量级的存储辅助类,用来保存应用的一些常用配置,它提供了string,set,int,long,float,boolean六种数据类型。最终数据是以xml形式进行存储。在应用中通常做一些简单数据的持久化缓存。

二、为什么要使用SharedPreferences?

首先我们要理解一下我们的程序是怎么工作的。我们的博客园APP需要不断地调用API从博客园官方数据库中获取数据,有些数据是每个用户独有的,有些数据是大家都能看的,这就导致每次请求数据时必须有一个身份认定来保护隐私。因此在用户登录后,我们会拿到一个Authorization_Code,它可以唯一标识一个用户。因此Authorization_Code是调用用户数据的关键,那么在我们的app中有5个模块,4个模块要用到Authorization_Code,只要有一个模块取得了Authorization_Code,必须通知到其它模块,不要再让用户登录了。这就需要我们用到单例模式来存储有关登录状态的信息。我们知道,虽然单例模式每次运行程序后只有一个实例,但是一旦我们退出程序重启,这个单例实例就会被重新创建,登录状态信息丢失,导致每次用户重新进入app后都要重新登录,造成了很大的不便。为了改善这一点,我们决定使用SharedPreferences来存储信息。

三、SharedPreferences存储机制

简单来说,SharedPreferences本质上使用的是文件存储,存储位置在/data/data/<程序包名>/shared_prefs/文件名.xml。在第一次创建这个文件后,只要用户不清理缓存,这个文件会一直存在。

四、简单示例

如何存储数据

public class Save extends AppCompatActivity {//这是一个activity
      private SharedPreferences sharedpreferences;
      private SharedPreferences.Editor editor;
      private String code = "Example";//要存储的数据
      @Override
      protected void onCreate(Bundle savedInstanceState) {//重写activity的onCreate方法
            super.onCreate(savedInstanceState);
            setContentView(R.layout.save_activity);
            sharedpreferences = getApplication().getSharedPreferences("User", Context.MODE_PRIVATE);//"User"是存储的文件名,Context.MODE_PRIVATE表示该文件只能被创建他的应用访问
            editor = sharedpreferences.edit();
            editor.putString("Code",code);//第一个参数相当于一个Key,后面取出数据时需要用到这个值来索引
            editor.commit();
      }
}

如何读取存储的数据

public class Read extends AppCompatActivity {//这是一个activity
      private SharedPreferences sharedpreferences;
      private String code;//要读取的数据
      @Override
      protected void onCreate(Bundle savedInstanceState) {//重写activity的onCreate方法
            super.onCreate(savedInstanceState);
            setContentView(R.layout.save_activity);
            sharedpreferences = getApplication().getSharedPreferences("User", Context.MODE_PRIVATE);//"User"是存储的文件名,Context.MODE_PRIVATE表示该文件只能被创建他的应用访问,必须与存储时写的格式一样,否则会找不到文件
            code = sharedpreferences.getString("Code","");//"Code"相当于Map中的Key,第二个参数""表示在没找到相应的数据时返回的值(默认值,可以用来判断其他地方是否导入过数据)
      }
}

五、注意事项

虽然SharedPreferences使用方便,功能也比较实用,但是SharedPreferences有一些性能缺陷。

1、加载缓慢。

SharedPreferences 文件的加载使用了异步线程,而且加载线程并没有设置优先级,如果这个时候读取数据就需要等待文件加载线程的结束。这就导致主线程等待低优先线程锁的问题,比如一个 100KB 的 SP 文件读取等待时间大约需要 50 ~ 100ms。

2、跨进程不安全

由于没有使用跨进程的锁,就算使用 MODE_MULTI_PROCESS,SharedPreferences 在跨进程频繁读写有可能导致数据全部丢失。根据线上统计,SharedPreferences 大约会有万分之一的损坏率。

3、造成程序卡顿。

由于提供了异步落盘的 apply 机制,在崩溃或者其它一些异常情况可能会导致数据丢失。所以当应用收到系统广播,或者被调用onPause等一些时机,系统会强制把所有的SharedPreferences对象的数据落地到磁盘。如果没有落地完成,这时候主线程会被一直阻塞。这样非常容易造成卡顿,甚至是ANR,从线上数据来看 SP 卡顿占比一般会超过5%。
所以建议大家在使用时尽量少用,只用SharedPreferences来存储少量数据

posted on 2020-05-20 23:10  Nergigante  阅读(496)  评论(0编辑  收藏  举报