上一节学习了文件存储方式,基本上所有的数据我们都可以通过文件去存,但是整体操作起来会比较麻烦,而且没有一个通用固定的数据结构,如果只需要存储一些轻量级的东西,比如“用户偏好”、“系统设置”、“开关值”等相关数据可能只需要一个 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 进行增删改查,对于轻量级数据来讲是个非常不错的选择。