iT邦幫忙

2025 iThome 鐵人賽

DAY 23
0

今天來介紹SharedPreferences,開始吧( • . • )

當我們需要儲存少量且簡單的資料,例如使用者的設定、登入狀態、或是一些 App 的旗標時,SharedPreferences是 Android 平台提供最輕量、最方便的解決方案。它讓你的 App 能夠持久地保存資料,即使 App 被關閉或裝置重新啟動,這些資料依然存在

什麼是 SharedPreferences?

SharedPreferences是 Android 提供的一個 API,專門用來儲存Key-Value Pairs 形式的原始資料型別,它會將這些資料儲存在一個 XML 檔案中,該檔案位於你的 App 的內部儲存空間,因此其他 App 無法存取,確保了資料的私密性

主要用途:

  • 儲存使用者偏好設定(例如:夜間模式開關、通知音效是否開啟)
  • 記錄 App 的狀態(例如:是否首次開啟)
  • 保存簡單的 session 資訊(例如:使用者名稱、登入憑證)

限制:SharedPreferences不適合用來儲存大量或複雜的資料,也不要直接儲存敏感性高的資訊(密碼之類的),因為它預設是未加密的

使用 SharedPreferences

SharedPreferences主要圍繞著取得實例、編輯、儲存和讀取

  • 取得SharedPreferences實例
    getSharedPreferences(檔案名稱, Context.MODE_PRIVATE);
    • 檔案名稱: 自訂你的 XML 檔案名稱。在整個 App 中使用同一個名稱就可以存取到同一個檔案。
    • MODE_PRIVATE: 這是預設且最常用的模式,表示該檔案只能被你的 App 存取
  • 編輯資料
    要寫入資料,要先從SharedPreferences 物件取得一個 Editor 物件
    SharedPreferences.Editor editor = prefs.edit();
  • 寫入/刪除資料
    使用 editorput 方法(如 putString(), putBoolean())來寫入資料,或用 remove()clear() 來刪除
  • 提交儲存
    寫入操作完成後,呼叫以下的其中一個方法提交變更:
    • apply(): 非同步儲存。它會立即更改記憶體中的SharedPreferences物件,並在背景執行緒中非同步地將變更寫入磁碟。它沒有回傳值,且不會阻塞 UI 執行緒
    • commit(): 同步儲存。它會阻塞 UI 執行緒,直到資料被成功寫入磁碟為止,並回傳一個布林值表示是否成功。應避免在主執行緒使用此方法

注意事項

  • 使用常數作為 Key:將所有SharedPreferences 的Key 定義成 public static final String 常數,可以集中管理並避免在程式碼中因拼寫錯誤而導致的 bug
  • 優先使用apply():除非你要立即知道寫入是否成功,不然盡量都使用 apply(),以避免阻塞 UI 執行緒
  • 不要儲存敏感資料:對於密碼、API Token 等敏感資訊,可以使用 Android Jetpack Security 函式庫中的 EncryptedSharedPreferences,它會自動對Key和Value加密
  • 保持簡潔:SharedPreferences的設計初衷是儲存少量、簡單的資料。不要用它來儲存複雜的 JSON 字串或大量的資料

範例

下面是簡單的小範例

xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp"
    android:gravity="center_horizontal"
    tools:context=".MainActivity">

    <EditText
        android:id="@+id/data_main_et"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:hint="輸入要儲存的文字"
        android:inputType="text"/>

    <Button
        android:id="@+id/save_main_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="儲存資料" />

    <Button
        android:id="@+id/load_main_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="載入資料" />

    <TextView
        android:id="@+id/result_main_tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="資料會顯示在這"
        android:textSize="20sp" />

</LinearLayout>

Java

package com.example.sharedpreferences_test;

import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    private EditText dataEditText;
    private Button saveButton;
    private Button loadButton;
    private TextView resultTextView;

    public static final String SHARED_PREFS_FILE_NAME = "MyPrefsFile";
    public static final String KEY_USER_DATA = "UserData";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        dataEditText = findViewById(R.id.data_main_et);
        saveButton = findViewById(R.id.save_main_btn);
        resultTextView = findViewById(R.id.result_main_tv);
        loadButton = findViewById(R.id.load_main_btn);

        saveButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SharedPreferences sharedPreferences = getSharedPreferences(SHARED_PREFS_FILE_NAME, Context.MODE_PRIVATE);
                //取得Editor
                SharedPreferences.Editor editorData = sharedPreferences.edit();
                //透過putString()寫入資料
                editorData.putString(KEY_USER_DATA, dataEditText.getText().toString());
                //儲存變更
                editorData.apply();
                Toast.makeText(MainActivity.this, "資料儲存!", Toast.LENGTH_SHORT).show();
            }
        });

        loadButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SharedPreferences sharedPreferences = getSharedPreferences(SHARED_PREFS_FILE_NAME, Context.MODE_PRIVATE);

                //透過getString()讀取資料
                String loadData = sharedPreferences.getString(KEY_USER_DATA, "找不到資料");

                //讀取到的資料設定到TextView
                resultTextView.setText(loadData);
                Toast.makeText(MainActivity.this, "資料已載入!", Toast.LENGTH_SHORT).show();
            }
        });
    }
}

今天就先介紹到這裡了,明天講TabLayout跟ViewPager,明天見ヽ(● - ● )ノ

https://ithelp.ithome.com.tw/upload/images/20251007/20176154ErErH17bDs.png


上一篇
Day22 SwipeRefreshLayout 介紹
下一篇
Day24 TabLayout搭配ViewPager介紹
系列文
Android 菜鳥30天從0到1的學習紀錄24
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言