首页 > 其他分享 >16.SharedPreferences存储

16.SharedPreferences存储

时间:2022-10-18 08:56:54浏览次数:60  
标签:存储 16 editor SharedPreferences import android inputType

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文件中是非常不安全的,很容易就会被别人盗取,因此在正式的项目里还需要结合一定的加密算法来对密码进行保护才行。

标签:存储,16,editor,SharedPreferences,import,android,inputType
From: https://www.cnblogs.com/lihuawei/p/16636949.html

相关文章

  • 【LeetCode】1672. 最富有客户的资产总量(C++)
    1672.最富有客户的资产总量(C++)​​1题目描述​​​​2示例描述​​​​2.1示例1​​​​2.2示例2​​​​2.3示例3​​​​3解题提示​​​​4源码详解(C++)​​1......
  • 一起学kubernetes系列(1)‌明明白白安装Kubernetes1.16.2
    ​前言首次安装Kubernetes我们采用kubeadm来安装单Master节点的方式,安装最新版的Kubernetes和Calico,一步一步循序渐进。介绍Master:集群控制管理节点,所有的命令都经由master......
  • 【LeetCode】1608. 特殊数组的特征值(C++)
    1608.特殊数组的特征值(C++)​​1题目描述​​​​2示例描述​​​​2.1示例1​​​​2.2示例2​​​​2.3示例3​​​​2.4示例4​​​​3解题提示​​​​4解题思......
  • Python学习:标准库之数据持久存储与交换
    持久存储数据以便长期使用包括两个方面:在对象的内存中表示和存储格式之间来回转换数据,以及处理转换后数据的存储区。标准库包含很多模块可以处理不同情况下的这两个方面......
  • PowerDesigner 16.5软件安装包下载及安装教程
    PowerDesigner16.5软件简介:PowerDesigner16.5是一款功能强大的数据库建模软件,采用模型驱动方法,将业务与IT结合起来,可帮助部署有效的企业体系架构,并为研发生命周期管理提供......
  • 1016 部分A+B(JAVA)
    正整数A的“DA(为1位整数)部分”定义为由A中所有DA组成的新整数PA。例如:给定A=3862767,DA=6,则A的“6部分”PA是66,因为A中有2个6。现给定A、DA、B、DB,请编......
  • 16.MongoDB系列之分片管理
    1.查看当前状态1.1查看配置信息mongos>useconfig//查看分片mongos>db.shards.find(){"_id":"study","host":"study/localhost:27018,localhost:27019,loc......
  • 计算机显示字符,从键盘输入到屏幕显示和存储
    1.由点成线,由线成面。2.将面拆分成一个个点组成,取较小的点抠出3.再将点按照正方形继续拆分成一个个粗粒度的点,按照黑白涂色,就组成了一个字符4.将黑白分别用1和0代替,将正......
  • NDB和InnoDB存储引擎之间的差异
    ​该​​NDB​​存储引擎采用分布式,无共享架构,这会导致它从行为不同的方式实现 ​​InnoDB​​在多种方式。对于那些不习惯使用的人来说 ​​NDB​​,由于其在交易,外键,表格......
  • day16异常以及生成器
    目录今日内容详细异常常见类型异常处理语法结构异常处理补充异常处理实战应用生成器对象课堂练习yield冷门用法生成器表达式今日内容详细异常常见类型AttributeError......