『Android基础入门』SharedPreferences简单数据存储【模拟QQ登录】

736 阅读5分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。 、

👨‍🎓作者简介:一位喜欢写作,计科专业的大二菜鸟

🏡个人主页:starry陆离

🕒首发日期:2022年6月23日星期四

🌌上期文章:『Android开源控件』SmartRefreshLayout实现下拉刷新,上划加载

📚订阅专栏:『Android基础入门』 如果文章有帮到你的话记得点赞👍+收藏💗支持一下哦


注意:不是教程只是笔记,如有错误欢迎批评指正

🍁官网简介

保存键值对数据 | Android 开发者 | Android Developers (google.cn)

如果您有想要保存的相对较小键值对集合,则应使用 SharedPreferences API。SharedPreferences 对象指向包含键值对的文件,并提供读写这些键值对的简单方法。每个 SharedPreferences 文件均由框架进行管理,可以是私有文件,也可以是共享文件。

例如:我们登录qq并不是每次都会要输入账号密码,而是会记住密码和用户的登录状态,这些轻量的数据可以通过SharedPreferences以键值对的方式存储在本地

🌾SharedPreferences的使用(模拟QQ登录)

这里我们创建三个Activity,分别代表QQ欢迎界面,用户登录界面和用户首页界面

image-20220427204358152

😁简单的为登录界面加一些组件

image-20220427205132787

activtiy_login.xml关键代码

 <?xml version="1.0" encoding="utf-8"?>
 <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     tools:context=".LoginActivity">
 ​
     <TextView
         android:id="@+id/textView"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_marginStart="52dp"
         android:layout_marginTop="160dp"
         android:text="账号:"
         android:textSize="20sp"
         android:textColor="@color/black"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toTopOf="parent" />
 ​
     <TextView
         android:id="@+id/textView2"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_marginTop="48dp"
         android:text="密码:"
         android:textSize="20sp"
         android:textColor="@color/black"
         app:layout_constraintStart_toStartOf="@+id/textView"
         app:layout_constraintTop_toBottomOf="@+id/textView" />
 ​
     <EditText
         android:id="@+id/editTextTextPersonName"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_marginStart="32dp"
         android:ems="10"
         android:inputType="textPersonName"
         android:text="Name"
         app:layout_constraintBottom_toBottomOf="@+id/textView"
         app:layout_constraintStart_toEndOf="@+id/textView"
         app:layout_constraintTop_toTopOf="@+id/textView" />
 ​
     <EditText
         android:id="@+id/editTextTextPassword"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:ems="10"
         android:inputType="textPassword"
         app:layout_constraintBottom_toBottomOf="@+id/textView2"
         app:layout_constraintStart_toStartOf="@+id/editTextTextPersonName"
         app:layout_constraintTop_toTopOf="@+id/textView2" />
 ​
     <Button
         android:id="@+id/button"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_marginTop="92dp"
         android:text="登录"
         android:textSize="20sp"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintHorizontal_bias="0.498"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toBottomOf="@+id/editTextTextPassword" />
 </androidx.constraintlayout.widget.ConstraintLayout>

😆在LoginActivity中写验证登录的逻辑代码

用户如果验证登录成功,我们要将用户的用户名以及登录状态通过SharedPreferences以键值对的形式保存在本地磁盘中,关键代码如下:

 //SharedPreferences是接口,并不是类
 /*getSharedPreferences(参数一,参数二)
 参数一: 存储数据的文件名
 参数二: 数据存储方式
  */
 //获取SharedPreferences对象
 SharedPreferences sp=getSharedPreferences("user",MODE_PRIVATE);
 //获取Editor对象的引用
 SharedPreferences.Editor editor=sp.edit();
 //将获取过来的值放入文件
 editor.putString("username","Starry陆离");
 editor.putBoolean("isLogin",true);
 //最后要提交数据到本地
 editor.commit();

可以看到getSharedPreferences();方法存储数据的方式有多种,其中3种已经在Android7.0中弃用

MODE_PRIVATE指定该SharedPreferences数据只能被本应用程序
MODE_APPEND该模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件;
MODE_WORLD_READABLE指定该SharedPreferences数据能被其他应用程序读,但不能写(不安全,已弃用)
MODE_WORLD_WRITEABLE指定该SharedPreferences数据能被其他应用程序读取和写入(不安全,已弃用)

image-20220427211602314

注意:自 API 级别 17 起,MODE_WORLD_READABLE 和 MODE_WORLD_WRITEABLE 模式已被弃用。 从 Android 7.0(API 级别 24)开始,如果您使用这些模式,Android 会抛出 SecurityException。如果您的应用需要与其他应用共享私有文件,可以通过 FLAG_GRANT_READ_URI_PERMISSION 使用 FileProvider。如需了解详情,另请参阅共享文件

除了可以储存字符串和布尔类型的数据,储存boolean,string,float,int,long,set六种数据类型。

它也有两个参数,前者是”键“,或者是“值”

image-20220427213353912

image-20220427210530989

LoginActivity完整代码

 ​
 public class LoginActivity extends AppCompatActivity {
 ​
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_login);
 ​
         EditText userNameEdit=findViewById(R.id.editTextTextPersonName);
         EditText userPwdEdit=findViewById(R.id.editTextTextPassword);
 ​
         Button loginBtn=findViewById(R.id.button);
 ​
         loginBtn.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View view) {
                 String userName=userNameEdit.getText().toString();
                 String userPwd=userPwdEdit.getText().toString();
                 if(userName.equals("starry")&&userPwd.equals("lx0411")){
                     //todo 跳转到主页面+保存用户名+登录状态
 ​
                     //SharedPreferences是接口,并不是类
                     /*
                     参数一:存储数据的文件名
                      */
                     //获取SharedPreferences对象
 ​
                     SharedPreferences sp=getSharedPreferences("user",MODE_PRIVATE);
                     //获取Editor对象的引用
                     SharedPreferences.Editor editor=sp.edit();
                     //将获取过来的值放入文件
                     editor.putString("username",userName);
                     editor.putBoolean("isLogin",true);
                     
                     //最后要提交数据到本地
                     editor.commit();
 ​
                     //登录成功,跳转到用户首页界面
                     Intent intent=new Intent(LoginActivity.this,MainActivity.class);
                     startActivity(intent);
                     Toast.makeText(LoginActivity.this,"登录成功",Toast.LENGTH_LONG).show();
 ​
                 }else{
                     Toast.makeText(LoginActivity.this,"登录失败",Toast.LENGTH_LONG).show();
                 }
             }
         });
 ​
     }
 }

😀用户首页界面添加文本组件

然后简单的为用户首页界面添加一个文本组件用来接受等会储存在SharedPreferences中的用户名

image-20220427214531734

activity_main.xml中的完整代码

 <?xml version="1.0" encoding="utf-8"?>
 <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     tools:context=".MainActivity">
 ​
     <TextView
         android:id="@+id/textview"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:text="Hello World!"
         android:textColor="@color/black"
         android:textSize="40sp"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintLeft_toLeftOf="parent"
         app:layout_constraintRight_toRightOf="parent"
         app:layout_constraintTop_toTopOf="parent" />
 ​
 </androidx.constraintlayout.widget.ConstraintLayout>

😊在MainActivity中获取到user文件

image-20220427220316930

MainActivity完整代码

 ​
 public class MainActivity extends AppCompatActivity {
 ​
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_main);
 ​
         TextView textView = findViewById(R.id.textView);
         //通过文件名获取到user文件
         SharedPreferences sp=getSharedPreferences("user",MODE_PRIVATE);
         //取出键名为username的用户名
         String userName=sp.getString("username","");
         //将用户名设置到文本组件中
         textView.setText(userName);
 ​
     }
 }

🤣为用户欢迎界面设置背景

图片可以在在网络上下载qq欢迎界面 - Bing images

image-20220427214757415

activity_welcome.xml中的完整代码

 <?xml version="1.0" encoding="utf-8"?>
 <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:background="@drawable/welcome"
     tools:context=".WelcomeActivity">
 ​
 </androidx.constraintlayout.widget.ConstraintLayout>

😒在WelcomeActivity中写一个新线程,获取到用户登录状态

image-20220427215803090

WelcomeActivity完整代码

 public class WelcomeActivity extends AppCompatActivity {
 ​
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_welcome);
 ​
         Thread thread = new Thread() {
             public void run() {
                 super.run();
 ​
                 try {
                     Thread.sleep(2000);
                 } catch (InterruptedException e) {
                     e.printStackTrace();
                 }
                 //读取用户的登录状态
                 SharedPreferences sp = getSharedPreferences("user", MODE_PRIVATE);
                 Boolean isLogin = sp.getBoolean("isLogin", false);
                     //如果登录状态是true则直接进入用户首页
                 if (isLogin) {
                     Intent intent = new Intent(WelcomeActivity.this, MainActivity.class);
                     startActivity(intent);
                 } else {
                     //否则跳转到用户登录界面
                     Intent intent = new Intent(WelcomeActivity.this, LoginActivity.class);
                     startActivity(intent);
                 }
             }
         };
         thread.start();
     }
 }

😘运行效果

通过动图可以发现用户第一次登录时是需要验证身份的,而第二次登录用户可以直接进入”qq首页界面“,这是因为我们第一次登录的时候将用户的登录状态记录在了user文件里,再次登陆时WelcomeActivity代码中读取到了用户的登录状态是true,所以直接跳转到用户首页界面 在这里插入图片描述

那么这个user文件保存在哪里呢?

可以看到在data/data/项目包名shared_prefs文件夹下生成了一个user.xml的文件,里面存放就是我们的用户名和登录状态信息

image-20220427223151226 在这里插入图片描述