1SharedPreferences存储

不同于文件的存储方式,SharedPreferences是使用键值对的方式来存储数据的,保存为.xml文件

也就是说当保存一条数据的时候,需要给这条数据提供一个对应的键,这样在读取数据的时候就可以通过这个键把相应的值取出来。

而且SharedPreferences还支持多种不同的数据类型存储,如果存储的数据类型是整型,那么读取出来的数据也是整型的,存储的数据是一个字符串,读取出来的数据仍然是字符串。

使用SharedPreferences来进行数据持久化要比使用文件方便很多,下面我们就来看一下它的具体用法吧。

(1)将数据存储到SharedPreferences中

要想使用SharedPreferences来存储数据,首先需要获取到SharedPreferences对象。

Android中主要提供了三种方法用于得到SharedPreferences对象。

1.Context类中的getSharedPreferences()方法(指定文件名

此方法接收两个参数,第一个参数用于指定SharedPreferences文件的名称,如果指定的文件不存在则会创建一个,SharedPreferences文件都是存放在/data/data/<package name>/shared_prefs/目录下的。

第二个参数用于指定操作模式,常用的模式有两种:MODE_PRIVATE和MODE_APPEND。

MODE_PRIVATE:默认模式,和直接传入0效果是相同的,表示只有当前的应用程序才可以对这个SharedPreferences文件进行读写。

MODE_APPEND:检查SharedPreferences文件是否存在,存在就往SharedPreferences文件里追加内容,否则就创建新文件。

MODE_MULTI_PROCESS:一般是用于会有多个进程中对同一个SharedPreferences文件进行读写的情况。现在官方已经将MODE_MULTI_PROCESS标记为弃用,推荐使用ContentProvider来进行进程间的数据共享,在MODE_MULTI_PROCESS模式下使用 SharedPreference 是不安全的。

另外,还有MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE这两种模式,表示当前文件可以被其他应用读取或读取写入,也已在Android 4.2版本中被废弃。

2.Activity类中的getPreferences()方法(固定文件名

这个方法和Context中的getSharedPreferences()方法很相似,不过它只接收一个操作模式参数,因为使用这个方法时会自动将当前活动的类名作为SharedPreferences的文件名。

3.PreferenceManager类中的getDefaultSharedPreferences()方法(固定文件名

这是一个静态方法,它接收一个Context参数,并自动使用当前应用程序的包名作为前缀来命名SharedPreferences文件。

得到了SharedPreferences对象之后,就可以开始向SharedPreferences文件中存储数据了,主要可以分为三步实现:

1.调用SharedPreferences对象的edit()方法获取一个SharedPreferences.Editor对象。

2.向SharedPreferences.Editor对象中添加数据,比如添加一个布尔型数据就使用putBoolean()方法,添加一个字符串则使用putString()方法,以此类推。

3.调用commit()方法将添加的数据提交,从而完成数据存储操作。

下面通过一个例子来体验一下SharedPreferences存储的用法吧。

新建一个SharedPreferencesTest项目,然后修改activity_main.xml中的代码,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity"> <Button
android:id="@+id/btnSaveData"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="存储数据" />

</LinearLayout>

这里我们不做任何复杂的功能,只是简单地放置了一个按钮,用于将一些固定数据存储到SharedPreferences文件当中。

然后修改MainActivity中的代码,如下所示:

import androidx.appcompat.app.AppCompatActivity;

import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.widget.Button; public class MainActivity extends AppCompatActivity {
private Button btnSaveData; // 存储数据按钮 @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); btnSaveData = (Button) findViewById(R.id.btnSaveData);
btnSaveData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SharedPreferences.Editor editor = getSharedPreferences("data", MODE_PRIVATE).edit(); // 获取Editor对象
editor.putString("姓名", "张三"); // 存储字符串型
editor.putInt("年龄", 36); // 存储整型
editor.putBoolean("是否在职", true); // 存储布尔型
editor.commit(); // 提交修改
}
});

}
}

可以看到,这里先给按钮注册了一个点击事件,然后在点击事件中通过getSharedPreferences()方法指定SharedPreferences的文件名为data,并通过其edit()方法得到了SharedPreferences.Editor对象。

接着向这个对象中添加了三条不同类型的数据,最后调用commit()方法进行提交,从而完成了数据存储的操作。

运行一下程序,进入程序的主界面后,点击一下“存储数据”按钮,这时的数据应该已经保存成功了。

不过为了要证实一下,我们还是要借助Device File Explorer来进行查看,进入到/data/data/com.sdbi.sharedpreferencestest/shared_prefs/目录下,可以看到生成了一个data.xml文件,双击打开,内容如图所示。

可以看到,我们刚刚在按钮的点击事件中添加的所有数据都已经成功保存下来了,并且SharedPreferences文件是使用XML格式来对数据进行管理的。

那么接下来我们再来学习,如何从SharedPreferences文件中去读取这些数据了。

(2)从SharedPreferences中读取数据

我们可以看到使用SharedPreferences来存储数据是非常简单的,其实从SharedPreferences文件中读取数据更加的简单。

SharedPreferences对象中提供了一系列的get方法用于对存储的数据进行读取,每种get方法都对应了SharedPreferences.Editor中的一种put方法,比如读取一个布尔型数据就使用getBoolean()方法,读取一个字符串就使用getString()方法。

这些get方法都接收两个参数,第一个参数是键,传入存储数据时使用的键就可以得到相应的值了,第二个参数是默认值,即表示当传入的键找不到对应的值时,会以什么样的默认值进行返回。

我们还是在SharedPreferencesTest项目的基础上继续开发,修改activity_main.xml中的代码,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity"> <Button
android:id="@+id/btnSaveData"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="存储数据" /> <Button
android:id="@+id/btnReadData"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="读取数据" />
</LinearLayout>

这里增加了一个“读取数据”的按钮,我们通过点击这个按钮来从SharedPreferences文件中读取数据。

修改MainActivity中的代码,如下所示:

import androidx.appcompat.app.AppCompatActivity;

import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button; public class MainActivity extends AppCompatActivity {
private Button btnSaveData; // 存储数据按钮
private Button btnReadData; // 读取数据按钮 @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); btnSaveData = (Button) findViewById(R.id.btnSaveData);
btnSaveData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SharedPreferences.Editor editor = getSharedPreferences("data", MODE_PRIVATE).edit(); // 获取Editor对象
editor.putString("姓名", "张三"); // 存储字符串型
editor.putInt("年龄", 36); // 存储整型
editor.putBoolean("是否在职", true); // 存储布尔型
editor.commit(); // 提交修改
}
});

btnReadData
= (Button) findViewById(R.id.btnReadData);
btnReadData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SharedPreferences sp = getSharedPreferences("data",
MODE_PRIVATE); // 获取SharedPreferences对象
String name = sp.getString("姓名", ""); // 读取字符串型
int age = sp.getInt("年龄", -1); // 读取整型
boolean job = sp.getBoolean("是否在职", false); // 读取布尔型
Log.d("MainActivity", "姓名 = " + name); // 输出姓名
Log.d("MainActivity", "年龄 = " + age); // 输出年龄
Log.d("MainActivity", "是否在职 = " + job); // 输出是否在职
}
});

}
}

可以看到,我们在“读取数据”按钮的点击事件中首先通过getSharedPreferences()方法得到了SharedPreferences对象,然后分别调用它的getString()、getInt()和getBoolean()方法去获取前面所存储的姓名、年龄和是否已婚,如果没有找到相应的值就会使用方法中传入的默认值来代替,最后通过Log将这些值打印出来。

现在重新运行一下程序,并点击界面上的“读取数据”按钮,然后查看Logcat中的打印信息,如图所示。

这样,所有之前存储的数据都成功读取出来了。

通过这个例子,我们就把SharedPreferences存储的知识也学习完了。

相比之下,SharedPreferences存储确实要比文本存储简单方便了许多,应用场景也多了不少,比如很多应用程序中的偏好设置功能其实都使用到了SharedPreferences技术。

那么下面我们就来编写一个记住密码的功能,相信通过这个例子能够加深你对SharedPreferences的理解。

(3)实现记住密码功能

我们来创建一个LoginTest项目,修改activity_main.xml中的代码,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"> <TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="用户名" /> <EditText
android:id="@+id/edtName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入用户名"
android:inputType="textPersonName" /> <TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="密码" /> <EditText
android:id="@+id/edtPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入密码"
android:inputType="textPassword" /> <CheckBox
android:id="@+id/checkPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="记住密码" />
<Button
android:id="@+id/btnLogin"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="登录" />
</LinearLayout>

这里使用到复选框控件,用户可以通过点击的方式来进行选中和取消,我们就使用这个控件来表示用户是否需要记住密码。

另外,对用户名和密码输入框,我们分别指定了android:inputType属性,下表详细列出了可选属性的意义:

android:inputType=“none”

android:inputType=“text”

android:inputType=“textCapCharacters”

字母大写

android:inputType=“textCapWords”

首字母大写

android:inputType=“textCapSentences”

仅第一个字母大写

android:inputType=“textAutoCorrect”

自动完成

android:inputType=“textAutoComplete”

自动完成

android:inputType=“textMultiLine”

多行输入

android:inputType=“textImeMultiLine”

输入法多行(如果支持)

android:inputType=“textNoSuggestions”

不提示

android:inputType=“textUri”

网址

android:inputType=“textEmailAddress”

电子邮件地址

android:inputType=“textEmailSubject”

邮件主题

android:inputType=“textShortMessage”

短讯

android:inputType=“textLongMessage”

长信息

android:inputType=“textPersonName”

人名

android:inputType=“textPostalAddress”

地址

android:inputType=“textPassword”

密码

android:inputType=“textVisiblePassword”

可见密码

android:inputType=“textWebEditText”

作为网页表单的文本

android:inputType=“textFilter”

文本筛选过滤

android:inputType=“textPhonetic”

拼音输入

数值类型

android:inputType=“number”

数字

android:inputType=“numberSigned”

带符号数字格式

android:inputType=“numberDecimal”

带小数点的浮点格式

android:inputType=“phone”

拨号键盘

android:inputType=“datetime”

时间日期

android:inputType=“date”

日期键盘

android:inputType=“time”

时间键盘

然后修改MainActivity中的代码,如下所示:

import androidx.appcompat.app.AppCompatActivity;

import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Toast; public class MainActivity extends AppCompatActivity {
private SharedPreferences pref;
private SharedPreferences.Editor editor;
private EditText edtName, edtPassword;
private Button btnLogin;
private
CheckBox checkPassword; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); pref = PreferenceManager.getDefaultSharedPreferences(this);
edtName = (EditText) findViewById(R.id.edtName);
edtPassword = (EditText) findViewById(R.id.edtPassword);
checkPassword = (CheckBox) findViewById(R.id.checkPassword);
btnLogin = (Button) findViewById(R.id.btnLogin);
boolean isCheckedPassword = pref.getBoolean("isCheckedPassword", false);
if (isCheckedPassword) {
// 将账号和密码都设置到文本框中
String name = pref.getString("name", "");
String password = pref.getString("password", "");
edtName.setText(name);
edtPassword.setText(password);
checkPassword.setChecked(true);
}
btnLogin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String name = edtName.getText().toString();
String password = edtPassword.getText().toString();
if (name.equals("admin") && password.equals("123456")) {
editor = pref.edit();
if (checkPassword.isChecked()) { // 检查复选框是否被选中
editor.putBoolean("isCheckedPassword", true);
editor.putString("name", name);
editor.putString("password", password);
} else {
editor.clear();
}
editor.commit();
finish();
} else {
Toast.makeText(MainActivity.this, "用户名或密码不正确"
, Toast.LENGTH_SHORT).show();
}
}
});

}
}

可以看到,这里首先在onCreate()方法中获取到了SharedPreferences对象,然后调用它的getBoolean()方法去获取isCheckedPassword这个键对应的值,一开始当然不存在对应的值了,所以会使用默认值false,这样就什么都不会发生。

接着在登录成功之后,会调用CheckBox的isChecked()方法来检查复选框是否被选中,如果被选中了表示用户想要记住密码,这时将isCheckedPassword设置为true,然后把name和password对应的值都存入到SharedPreferences文件当中并提交。

如果没有被选中,就简单地调用一下clear()方法,将SharedPreferences文件中的数据全部清除掉。

当用户选中了记住密码复选框,并成功登录一次之后,isCheckedPassword键对应的值就是true了,这个时候如果再重新启动登录界面,就会从SharedPreferences文件中将保存的账号和密码都读取出来,并填充到文本输入框中,然后把记住密码复选框选中,这样就完成记住密码的功能了。

现在重新运行一下程序,然后账号输入admin,密码输入123456,并选中记住密码复选框,点击登录,然后退出程序再次打开程序,重新回到登录界面,此时你会发现,账号密码都已经自动填充到界面上了,如图所示。

这样我们就使用SharedPreferences技术将记住密码功能成功实现了,不过需要注意,这里实现的记住密码功能仍然还只是个简单的示例,并不能在实际的项目中直接使用。

因为将密码以明文的形式存储在SharedPreferences文件中是非常不安全的,很容易就会被别人盗取,因此在正式的项目里还需要结合一定的加密算法来对密码进行保护才行。

最新文章

  1. git 回滚
  2. Java网络通信初步认知
  3. c语言中动态数组的建立
  4. FFTW中文参考
  5. 分析windows宿主机Ping不通linux虚拟机的其中一种情况
  6. How to center a div in bootstrap3
  7. 20160427Struts2--入门1
  8. android常见错误-Installation error: INSTALL_FAILED_INSUFFICIENT_STORAGE
  9. 分享一下常用的hosts列表
  10. UEditor配置图片上传
  11. oracle_数据库访问问题
  12. template.helper()方法
  13. nginx配置文件详解----第一篇【访问与错误日志】
  14. MQTT研究之EMQ:【JAVA代码构建X509证书】
  15. logback.xml例子
  16. ssh 公钥无秘登录问题
  17. TS - 问题分析与处理的一般性方法
  18. Ubuntu12.04下解决sudo apt-get update警告Duplicate sources.list entry
  19. CentOS6.5安装与配置Mysql数据库
  20. HTMl学习笔记02-编辑器

热门文章

  1. Redis01 Redis详细介绍
  2. day11-JSON处理和HttpMessageConverter&lt;T&gt;
  3. 开源免费视频会议Jitsi-meet介绍
  4. 消息传递(news)题解
  5. 跳板攻击之:frp代理转发
  6. 深入解读.NET MAUI音乐播放器项目(三):界面交互
  7. 爬虫下载rockchip的规格书
  8. 信息学奥赛介绍-CSP
  9. ES6判断对象是否为空
  10. leetcode刷题(三)