SharedPreferences 存儲
上一節(jié)學(xué)習(xí)了文件存儲方式,基本上所有的數(shù)據(jù)我們都可以通過文件去存,但是整體操作起來會比較麻煩,而且沒有一個通用固定的數(shù)據(jù)結(jié)構(gòu),如果只需要存儲一些輕量級的東西,比如“用戶偏好”、“系統(tǒng)設(shè)置”、“開關(guān)值”等相關(guān)數(shù)據(jù)可能只需要一個 Boolean 或者一個 Int 即可,那么 SharedPreferences 則是一個非常輕量簡單的選擇。
1. SharedPreferences 特點(diǎn)
在 Android 中,Shared Preferences 專門用于存儲一些基本數(shù)據(jù)類型(integer, float, boolean, string, long),它通過一種Key-Value的數(shù)據(jù)結(jié)構(gòu)存儲在私有目錄中。
我們可以通過 Shared Preferences 的接口獲取一個指向 Key-Value 文件的對象,相比操作文件可以更輕松的通過 Shared Preferences 進(jìn)行數(shù)據(jù)的讀取和寫入。該接口由 Android 系統(tǒng)負(fù)責(zé)管理,我們可以在任何地方通過接口操作 Shared Preferences,而且只有自己的 App 能夠訪問,是比較安全的存儲方式,非常適合存儲一些輕量級的數(shù)據(jù),類似“記住密碼”、“自動登錄”、“各種設(shè)置”的場景。
2. 處理 SharedPreferences
我們可以選擇將所有的數(shù)據(jù)存在一個 SharedPreferences 文件中或者分成多個文件存儲,取決于具體業(yè)務(wù)需求,系統(tǒng)提供了兩個 Api 供我們使用:
- getPreferences():
Activity 級別的 API,系統(tǒng)會給每個 Activity 創(chuàng)建一個獨(dú)立的 SharedPreferences 文件,各自 Activity 管理各自的數(shù)據(jù)。 - getSharedPreferences():
App 級別的 API,沒有 Activity 的限制,通過傳入的參數(shù)來決定用哪個 SharedPreferences 文件。
兩種 API 的使用示例如下:
SharedPreferences sharedPref = getPreferences(Context.MODE_PRIVATE);
SharedPreferences sharedPref = getSharedPreferences("filename", Context.MODE_PRIVATE);
第二個 API 的 fileName 就告訴系統(tǒng)采用哪個 SharedPreferences 文件。
3. SharedPreferences 的讀寫
和 File 一樣,SharedPreferences 的主要操作也是讀寫,不過相比之下 SharedPreferences 簡單很多。
3.1 寫入
為了將數(shù)據(jù)存儲到 SharedPreferences 文件中,我們需要一個editor
對象來編輯數(shù)據(jù)并保存到 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();
可以發(fā)現(xiàn),我們是通過sharedPref.edit()
方法來獲取 editor 對象的,我們可以用 Key-Value 的形式添加一些基本類型變量,最后通過commit()
方法提交即可。
3.2 讀取
在寫入之后,我們可以通過以下方式進(jìn)行數(shù)據(jù)讀?。?/p>
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 刪除數(shù)據(jù)
雖然 SharedPreferences 保存的都是輕量級的數(shù)據(jù),但是過多仍然會造成一些磁盤空間的占用,所以需要對于不用的數(shù)據(jù)進(jìn)行及時的刪除,可以通過remove ()
接口進(jìn)行刪除。
SharedPreferences pref = getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = pref.edit();
editor.remove("key");
editor.commit();
3.4 清空
我們還可以通過clear()
接口直接清空所有數(shù)據(jù):
SharedPreferences pref = getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = pref.edit();
editor.clear();
editor.commit();
記得在使用“editor”對象的相關(guān)操作之后,一定要調(diào)用commit()
方法將修改進(jìn)行 提交。
4. SharedPreferences 使用示例
本節(jié)來做一個登錄頁面,我們通過 SharedPreferences 來記錄當(dāng)前的登陸狀態(tài),只要用戶成功登陸過,那么下次登錄我們會讀取 SharedPreferences,一旦發(fā)現(xiàn)已登錄就可以免登陸直接進(jìn)入登錄態(tài),這也是一個很常見的場景。
4.1 登錄頁面的編寫
登錄頁面就是主頁的 XML 布局文件,核心就是兩個輸入框,分別對應(yīng)“賬號”和“密碼”,另外就是一個確認(rèn)登錄的 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 中,然后跳轉(zhuǎn)到登錄成功的頁面即可。
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("慕課網(wǎng)")) {
SharedPreferences.Editor editor = pref.edit();
editor.putString("username", username);
editor.putString("password", password);
editor.commit();
Toast.makeText(getApplicationContext(), "登陸成功", Toast.LENGTH_SHORT).show();
// 3、賬號密碼正確,跳轉(zhuǎn)
startActivity(intent);
} else {
// 4、輸入錯誤
Toast.makeText(getApplicationContext(), "賬號或者密碼錯誤", Toast.LENGTH_SHORT).show();
}
}
});
}
}
首先我們檢查已經(jīng)登錄成功過,是就直接跳轉(zhuǎn),否則等待用戶輸入賬號密碼,在登錄成功之后寫入 SharePreferenced 并跳轉(zhuǎn)。
4.3 登錄后的頁面
創(chuàng)建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>
主要是一個歡迎頁面,帶上了用戶的賬號名,另外就是一個“注銷登錄”按鈕,可以刪除登錄記錄并跳轉(zhuǎn)回登錄首頁,登陸成功后頁面如下:
4.4 登錄后的邏輯控制
登錄后需要實(shí)現(xiàn)一個歡迎標(biāo)語以及注銷的邏輯:
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. 小結(jié)
本節(jié)學(xué)習(xí)了第二個存儲方式,SharedPreferences 相比 File 更加輕量簡單,適合于存儲一些基礎(chǔ)類型的 Key-Value 對。比如“設(shè)置”、“開關(guān)”、“登錄”等等場景,根據(jù)不同的業(yè)務(wù)場景我們可以選擇將不同的數(shù)據(jù)放在不同的 SharedPreferences 文件中,然后通過系統(tǒng) API 進(jìn)行增刪改查,對于輕量級數(shù)據(jù)來講是個非常不錯的選擇。