章节索引 :

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>

登录界面如下:

login

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>

主要是一个欢迎页面,带上了用户的账号名,另外就是一个“注销登录”按钮,可以删除登录记录并跳转回登录首页,登陆成功后页面如下:

logout

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 进行增删改查,对于轻量级数据来讲是个非常不错的选择。

环境搭建,开发相关
Android 系统背景及结构概述 Android 开发环境搭建 Genymotion 的安装与使用 Android 工程解析及使用 Android 程序签名打包
常用 UI 布局
Android 的 UI 根基 View与View Android 线性布局 LinearLayout Android相对布局RelativeLayout Android 表格布局 TableLayout Android 网格布局 GridLayout Android 帧布局 FrameLayout Android绝对布局AbsoluteLayout
基础控件
Android 文本框 TextView Android 文本输入框 EditText 按钮 Button/ImageButton 选择框 RadioButton/Check 开关控件ToggleButton/Switch Android 图片控件 ImageView Android 进度条 ProgressBar Android 拖动条 SeekBar Android 评分条 RatingBar Android 滚动条 ScrollView 轮播滚动视图 ViewFlipper
Adapter 相关控件
Android 适配器 Adapter Android 列表控件 ListView Android 网格视图 GridView Android 下拉选择框 Spinner 自动补全文本框 AutoCompleteText 折叠列表 ExpandableListView
提示类控件
吐司提示:Toast 的使用方法 状态栏通知:Notification 对话框:AlertDialog 悬浮窗:PopupWindow
菜单类控件
菜单:Menu
其他控件
视频页面:ViewPager 侧滑菜单:DrawerLayout
事件处理机制
基于监听的事件处理机制 Handler 消息传递机制 触摸事件分发处理 AsyncTask:异步任务 Android 手势处理
Android 四大组件
活动:Activity 服务:Service 广播接收器:Broadcast Receiver 内容提供者 - Content Provider
数据存储
文件存储 SharedPreferences 存储 数据库:SQLite 的使用
网络编程
HTTP 使用详解 xml 数据解析 JSON 数据解析 网页视图:WebView Socket 网络接口
绘图与动画
图片资源:Drawable 位图:Bitmap
多媒体开发
媒体播放器:MediaPlayer 相机:Camera 音频录制:MediaRecorder
并发编程
多线程