深入剖析Android中最简单的数据存储方式:SharedPreferences

207 阅读8分钟

这是我参与8月更文挑战的第6天,活动详情查看:8月更文挑战

目录

一. 使用SharedPreferences存储数据

二. 数据的存储位置和格式

三、存储数据的获取

四. 存取复杂类型的数据

五. 设置数据文件的访问权限

Hello,你好呀,我是灰小猿,一个超会写bug的程序猿!

时隔好几天,我又回来了,最近一直忙着考试没时间更新~

今天来和大家分享一篇有关Android中数据存储的文章,它可以说是Android对数据的所有存储方式中最简单的一种存储了,它就是SharedPreferences.

这篇文章,我将详细的和大家讲一下如何使用SharePreferences进行数据的存储和读取,

一. 使用SharedPreferences存储数据

使用SharedPreferences进行存储的数据是存放在一个XML文件中的,同时它的存储方式是是以key-value的形式,key对应着将要存储的数据的名称,value对应存储的值,

使用 SharedPreferences 保存key-value对的步骤一般是这样:

1、使用Activity类的getSharedPreferences方法获取到 SharedPreferences 对象,并且在其中指定文件名和该文件的访问权限。在使用该方法时,如果该名称的文件不存在就创建爱你它,如果存在就直接打开。

SharedPreferences sharedPreferences = getSharedPreferences("logininfo", MODE_PRIVATE);

其中的第一个参数是文件名,第二个参数是访问权限,我们平常都会将其访问权限设置为private类型,以保护数据不被外界所访问

2、通过sharedPreferences的**edit()**方法,我们可以获取到该对象的修改权限,并返回SharedPreferences.Editor对象,

SharedPreferences.Editor edits = sharedPreferences.edit();

3、使用该对象的 putXxx方法保存key-value对。如我们要在文件中保存用户名为“张三”的这条信。

edits.putString("username",张三);

4、**通过SharedPreferences.Editor的commit方法保存(提交)key-value对。**这样该条信息就会被写入到文件中,并且在不删除的情况下会一直保存。

edits.commit();

下面我们通过一个实例来完整的看下数据存储到SharedPreferences的过程,存储用户登录的用户名和密码。

//获取一个文件名为login、权限为private的xml文件的SharedPreferences对象
SharedPreferences sharedPreferences = getSharedPreferences("login", MODE_PRIVATE);

//得到SharedPreferences.Editor对象,并保存数据到该对象中
SharedPreferences.Editor editor = sharedPreferences.edit();

//保存key-value对到文件中
editor.putString("username", “灰小猿”);
editor.putString("password", “123456”);

editor.commit();

我们上面也说过,使用该对象的 putXxx方法保存key-value对。

所以 SharedPreferences 提供可以直接保存的数据格式肯定不仅只有String,还有 int、boolean、float、long以及Set。但是存储数据的方式都是一样的步骤。

二. 数据的存储位置和格式

既然是将数据存储到了文件中,那么总会有文件的存储位置的,实际上,SharedPreferences 将数据文件写在了手机内存私有的目录中该app的文件夹下。

下面是在AndroidStudio中查看该文件的方法。

首先打开手机文件的存放目录【File Explorer】,在里面找到data\data\程序包名\shared_prefs目录,

就可以发现你命名的login****.xml文件。

点击文件并查看:

<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
    <string name="username">灰小猿</string>
    <string name="password">123456</string>
</map>

三、存储数据的获取

上面我们已经讲解了如何对数据进行存储,那么这些存储的数据我们是应该如何获取的呢?

其实通过sharedPreferences存储的数据的读取也是十分容易的,我们只需要使用getSharedPreferences()方法获取到对应的XML文件之后,使用其getXxx方法传入存储时的key即可,

代码如下:

SharedPreferences sharedPreferences = getSharedPreferences("logininfo", MODE_PRIVATE);
String username = sharedPreferences.getString("username", "");
String password = sharedPreferences.getString("password", "");

其中的getString()方法中的第一个参数是key的名称,

第二个参数的含义是:“如果没有找到以该key存储的value,那就返回该参数”,如上代码,没有相应的username或password的话就返回“”。

四. 存取复杂类型的数据

如果要用 SharedPreferences 存取复杂的数据类型(类,图像等),就需要对这些数据进行编码。通常会将复杂类型的数据转换成Base64编码,然后将转换后的数据以字符串的形式保存在XML文件中。

实例:
使用 SharedPreferences 保存Product类的一个对象和一张图片。

这里提供了两个Button,用来保存和获取使用 SharedPreferences 保存的Product对象和图片。

保存按钮的点击事件:

bt_prod_save.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {

                    //保存对象
                    Product product = new Product();
                    product.setId(et_prod_id.getText().toString().trim());
                    product.setName(et_prod_name.getText().toString().trim());

                    SharedPreferences sharedPreferences = getSharedPreferences("base64", MODE_PRIVATE);
                    SharedPreferences.Editor editor = sharedPreferences.edit();

                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
                    ObjectOutputStream oos = new ObjectOutputStream(baos);
                    oos.writeObject(product);
                    String base64Product = Base64.encodeToString(baos.toByteArray(), Base64.DEFAULT);

                    editor.putString("product", base64Product);

                    //保存图片
                    ByteArrayOutputStream baos2 = new ByteArrayOutputStream();
                    ((BitmapDrawable) getResources().getDrawable(R.drawable.lanbojini)).getBitmap().compress(Bitmap.CompressFormat.JPEG, 100, baos2);
                    String imageBase64 = Base64.encodeToString(baos2.toByteArray(), Base64.DEFAULT);

                    editor.putString("productImg", imageBase64);
                    editor.commit();
                    baos.close();
                    oos.close();

                    Toast.makeText(MainActivity.this, "保存成功!!!", Toast.LENGTH_SHORT).show();
                } catch (Exception e) {
                    Toast.makeText(MainActivity.this, "保存出错了!!!" + e.getMessage(), Toast.LENGTH_SHORT).show();

                }

            }

    });

回显按钮的点击事件:

bt_prod_show.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                try {
                    //获取对象
                    et_prod_id = (EditText) findViewById(R.id.et_prod_id);
                    et_prod_name = (EditText) findViewById(R.id.et_prod_name);
                    SharedPreferences sharedPreferences = getSharedPreferences("base64", MODE_PRIVATE);
                    String productString = sharedPreferences.getString("product", "");
                    byte[] base64Product = Base64.decode(productString, Base64.DEFAULT);
                    ByteArrayInputStream bais = new ByteArrayInputStream(base64Product);
                    ObjectInputStream ois = new ObjectInputStream(bais);

                    Product product = (Product) ois.readObject();
                    et_prod_id.setText(product.getId());
                    et_prod_name.setText(product.getName());

                    //获取图片
                    iv_prod_img = (ImageView) findViewById(R.id.iv_prod_img);
                    byte[] imagByte = Base64.decode(sharedPreferences.getString("productImg",""), Base64.DEFAULT);
                    ByteArrayInputStream bais2 = new ByteArrayInputStream(imagByte);
                    iv_prod_img.setImageDrawable(Drawable.createFromStream(bais2,  "imagByte"));

                } catch (Exception e) {

                    e.printStackTrace();

                }
            }
        });

原理:使用Base64把Product对象和图片进行编码成字符串后,然后通过 SharedPreferences 把转换后的字符串保存到xml文件中,在需要使用该对象或者图片时,通过Base64把从 SharedPreferences 获取的字符串解码成对象或者图片再使用。

查看base64.xml 文件,会看到如下内容:

<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
    <string name="productImg">/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDABALDA4MChAOoOjM9PDkz......
    </string>
    <string name="product">rO0ABXNyACNjbHViLmxldGdldC50ZXN0c2hhGJqb......
    </string>
</map>

注意:
虽然可以采用编码的方式通过 SharedPreferences 保存任何类型的数据,但不建议使用 SharedPreferences 保存尺寸很大的数据。如果要存取更多的数据,一般使用文件存储、SQLite数据库等技术。

五. 设置数据文件的访问权限

我们知道Android系统本质上是Linux,那么Android文件权限也和Linux一致。Linux文件属性分为4段,
第一段:

  • [d]:表示目录
  • [-]:表示文件
  • [l]:表示链接文件
  • [b]:表示可供存储的接口设备文件
  • [c]:表示串口设备文件,例如键盘、鼠标

第二段:

  • [r]:表示可读
  • [w]:表示可写
  • [x]:表示可执行

如果不具备某个属性,该项将以[-]代替,例如rw-、--x等
第三段和第四段和第二段相同,区别在于,第二段表示文件所有者拥有的权限,第三段表示文件所有者所在的用户组中其他用户的权限,第四段表示其他用户的权限。

例如:-rw-rw-rw,表示这是一个文件,并且该用户和该组内其他用户和其他用户的权限都为可读和可写不可执行。

那么现在来对比一下我们这篇文章中文件的存储权限,我们在获取 SharedPreferences 对象时,使用的是下面这行代码:
SharedPreferences sharedPreferences = this.getSharedPreferences("test", MODE_PRIVATE);
其中
getSharedPreferences
方法第二个参数就是对文件权限的描述。

这个参数有四个可选值:

  • **Activity.MODE_PRIVATE:**表示该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容
  • **Activity.MODE_APPEND:**也是私有数据,新写入的内容会追加到原文件中
  • **Activity.MODE_WORLD_READABLE:**表示当前文件可以被其他应用读取
  • **Activity.MODE_WORLD_WRITEABLE:**表示当前文件可以被其他应用写入

但是出于对数据文件安全性的考虑,我们一般使用MODE_PRIVATE权限对文件进行存储。

好了,关于Android中使用SharedPreferences对数据进行存储的方法就和大家分享到这里,

有问题的小伙伴可以评论区留言或者添加我的微信!

我是灰小猿,我们下期见!