本文已参与「新人创作礼」活动,一起开启创作之路。 、
作者简介:一位喜欢写作,计科专业的大二菜鸟
个人主页:starry陆离
首发日期:2022年6月23日星期四
上期文章:『Android开源控件』SmartRefreshLayout实现下拉刷新,上划加载
订阅专栏:『Android基础入门』 如果文章有帮到你的话记得点赞+收藏支持一下哦
注意:不是教程只是笔记,如有错误欢迎批评指正
官网简介
保存键值对数据 | Android 开发者 | Android Developers (google.cn)
如果您有想要保存的相对较小键值对集合,则应使用 SharedPreferences
API。SharedPreferences
对象指向包含键值对的文件,并提供读写这些键值对的简单方法。每个 SharedPreferences
文件均由框架进行管理,可以是私有文件,也可以是共享文件。
例如:我们登录qq并不是每次都会要输入账号密码,而是会记住密码和用户的登录状态,这些轻量的数据可以通过SharedPreferences
以键值对的方式存储在本地
SharedPreferences的使用(模拟QQ登录)
这里我们创建三个Activity,分别代表QQ欢迎界面,用户登录界面和用户首页界面
简单的为登录界面加一些组件
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数据能被其他应用程序读取和写入(不安全,已弃用) |
注意:自 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六种数据类型。
它也有两个参数,前者是”键“,或者是“值”
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
中的用户名
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文件
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
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
中写一个新线程,获取到用户登录状态
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的文件,里面存放就是我们的用户名和登录状态信息