SharedPreferences 存储
上一节学习了文件存储方式,基本上所有的数据我们都可以通过文件去存,但是整体操作起来会比较麻烦,而且没有一个通用固定的数据结构,如果只需要存储一些轻量级的东西,比如“用户偏好”、“系统设置”、“开关值”等相关数据可能只需要一个 Boolean 或者一个 Int 即可,那么 SharedPreferences 则是一个非常轻量简单的选择。
1. SharedPreferences 特点
在 Android 中,Shared Preferences 专门用于存储一些基本数据类型(integer, float, boolean, string, long),它通过一种Key-Value的数据结构存储在私有目录中。
我们可以通过 Shared Preferences 的接口获取一个指向 Key-Value 文件的对象,相比操作文件可以更轻松的通过 Shared Preferences 进行数据的读取和写入。该接口由 Android 系统负责管理,我们可以在任何地方通过接口操作 Shared Preferences,而且只有自己的 App 能够访问,是比较安全的存储方式,非常适合存储一些轻量级的数据,类似“记住密码”、“自动登录”、“各种设置”的场景。
2. 处理 SharedPreferences
我们可以选择将所有的数据存在一个 SharedPreferences 文件中或者分成多个文件存储,取决于具体业务需求,系统提供了两个 Api 供我们使用:
- getPreferences():
Activity 级别的 API,系统会给每个 Activity 创建一个独立的 SharedPreferences 文件,各自 Activity 管理各自的数据。 - getSharedPreferences():
App 级别的 API,没有 Activity 的限制,通过传入的参数来决定用哪个 SharedPreferences 文件。
两种 API 的使用示例如下:
SharedPreferences sharedPref = getPreferences(Context.MODE_PRIVATE);
SharedPreferences sharedPref = getSharedPreferences("filename", Context.MODE_PRIVATE);
第二个 API 的 fileName 就告诉系统采用哪个 SharedPreferences 文件。
3. SharedPreferences 的读写
和 File 一样,SharedPreferences 的主要操作也是读写,不过相比之下 SharedPreferences 简单很多。
3.1 写入
为了将数据存储到 SharedPreferences 文件中,我们需要一个editor
对象来编辑数据并保存到 SharedPreferences 对象中。下面是一段editor
的使用示例代码:
SharedPreferences sharedPref = getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putBoolean("keyb",true);
editor.putString("keys","string value");
editor.putInt("keyi","int value");
editor.putFloat("keyf","float value");
editor.putLong("keyl","long value");
editor.commit();
可以发现,我们是通过sharedPref.edit()
方法来获取 editor 对象的,我们可以用 Key-Value 的形式添加一些基本类型变量,最后通过commit()
方法提交即可。
3.2 读取
在写入之后,我们可以通过以下方式进行数据读取:
SharedPreferences pref = getPreferences(Context.MODE_PRIVATE);
pref.getString("keys",null);
pref.getInt("keyi",0);
pref.getFloat("keyf",0);
pref.getBoolean("keyb",true);
pref.getLong("keyl",0);
3.3 删除数据
虽然 SharedPreferences 保存的都是轻量级的数据,但是过多仍然会造成一些磁盘空间的占用,所以需要对于不用的数据进行及时的删除,可以通过remove ()
接口进行删除。
SharedPreferences pref = getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = pref.edit();
editor.remove("key");
editor.commit();
3.4 清空
我们还可以通过clear()
接口直接清空所有数据:
SharedPreferences pref = getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = pref.edit();
editor.clear();
editor.commit();
记得在使用“editor”对象的相关操作之后,一定要调用commit()
方法将修改进行 提交。
4. SharedPreferences 使用示例
本节来做一个登录页面,我们通过 SharedPreferences 来记录当前的登陆状态,只要用户成功登陆过,那么下次登录我们会读取 SharedPreferences,一旦发现已登录就可以免登陆直接进入登录态,这也是一个很常见的场景。
4.1 登录页面的编写
登录页面就是主页的 XML 布局文件,核心就是两个输入框,分别对应“账号”和“密码”,另外就是一个确认登录的 Button。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/account"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="100dp"
android:layout_marginTop="150dp"
android:text="账号:" />
<EditText
android:id="@+id/et_account"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="100dp"
android:ems="10" />
<TextView
android:id="@+id/password"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="100dp"
android:text="密码:" />
<EditText
android:id="@+id/et_password"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="100dp"
android:ems="10"
android:inputType="textPassword" />
<Button
android:id="@+id/login"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="100dp"
android:text="登录" />
</LinearLayout>
登录界面如下:
4.2 登录 Activity
登录的逻辑主要是匹配账号和密码,如果通过我们记录一个登陆成功的 Key-Value 到 SharedPreferences 中,然后跳转到登录成功的页面即可。
package com.emercy.myapplication;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity {
EditText userName, pwd;
Button loginBtn;
SharedPreferences pref;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
userName = findViewById(R.id.et_account);
pwd = findViewById(R.id.et_password);
loginBtn = findViewById(R.id.login);
pref = getSharedPreferences("user_details", MODE_PRIVATE);
final Intent intent = new Intent(MainActivity.this, SecondActivity.class);
// 1、检查是否登录成功
if (pref.contains("username") && pref.contains("password")) {
startActivity(intent);
}
loginBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 2、输入账号密码
String username = userName.getText().toString();
String password = pwd.getText().toString();
if (username.equals("超低空") && password.equals("慕课网")) {
SharedPreferences.Editor editor = pref.edit();
editor.putString("username", username);
editor.putString("password", password);
editor.commit();
Toast.makeText(getApplicationContext(), "登陆成功", Toast.LENGTH_SHORT).show();
// 3、账号密码正确,跳转
startActivity(intent);
} else {
// 4、输入错误
Toast.makeText(getApplicationContext(), "账号或者密码错误", Toast.LENGTH_SHORT).show();
}
}
});
}
}
首先我们检查已经登录成功过,是就直接跳转,否则等待用户输入账号密码,在登录成功之后写入 SharePreferenced 并跳转。
4.3 登录后的页面
创建second.xml
,作为登录后页面的布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/result"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="170dp"
android:textSize="20sp" />
<Button
android:id="@+id/logout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="20dp"
android:text="注销登录" />
</LinearLayout>
主要是一个欢迎页面,带上了用户的账号名,另外就是一个“注销登录”按钮,可以删除登录记录并跳转回登录首页,登陆成功后页面如下:
4.4 登录后的逻辑控制
登录后需要实现一个欢迎标语以及注销的逻辑:
package com.emercy.myapplication;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class SecondActivity extends Activity {
SharedPreferences sharedPreferences;
Intent intent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second);
TextView result = findViewById(R.id.result);
Button btnLogOut = findViewById(R.id.logout);
sharedPreferences = getSharedPreferences("user_details", MODE_PRIVATE);
intent = new Intent(SecondActivity.this, MainActivity.class);
result.setText("欢迎您, " + sharedPreferences.getString("username", null));
btnLogOut.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.clear();
editor.commit();
startActivity(intent);
}
});
}
}
5. 小结
本节学习了第二个存储方式,SharedPreferences 相比 File 更加轻量简单,适合于存储一些基础类型的 Key-Value 对。比如“设置”、“开关”、“登录”等等场景,根据不同的业务场景我们可以选择将不同的数据放在不同的 SharedPreferences 文件中,然后通过系统 API 进行增删改查,对于轻量级数据来讲是个非常不错的选择。