שימוש בערכי העדפה שמורים חלק מ-Android Jetpack.

במסמך הזה מוסבר איך לאחסן את המידע ואיך להשתמש בו הערכים של Preference שנשמרים לפי ספריית ההעדפות.

אחסון נתונים לפי העדפות

בקטע הזה מתואר איך Preference יכול לשמור נתונים.

העדפות משותפות

כברירת מחדל, Preference משתמש SharedPreferences כדי לחסוך ערכים. ה-API של SharedPreferences תומך בקריאה ובכתיבה פשוטות צמדי מפתח/ערך מקובץ שנשמר בכל הסשנים באפליקציות. ספריית ההעדפות משתמשת במופע SharedPreferences פרטי, כך שרק יכול לגשת אליו.

לדוגמה, נניח את הדברים הבאים SwitchPreferenceCompat:

<SwitchPreferenceCompat
        app:key="notifications"
        app:title="Enable message notifications"/>

כשמשתמש מעביר את המתג הזה למצב 'מופעל' המצב, הקובץ SharedPreferences מתעדכנת באמצעות צמד מפתח/ערך של "notifications" : "true". המפתח שבו נעשה שימוש הוא זהה למפתח שהוגדר ל-Preference.

מידע נוסף על API של SharedPreferences זמין במאמר שמירת מפתח-ערך .

למידע על הדרכים השונות לאחסון נתונים ב-Android, ראו נתונים וסקירה כללית בנושא אחסון קבצים.

PreferenceDataStore

למרות שספריית ההעדפות שומרת נתונים עם SharedPreferences עד ברירת המחדל, SharedPreferences הם לא תמיד פתרון אידיאלי. לדוגמה, אם כדי שהאפליקציה שלכם דורשת מהמשתמש להיכנס, אולי כדאי להמשיך את ההגדרות של האפליקציה בענן, כך שההגדרות באות לידי ביטוי מכשירים ופלטפורמות אחרים. באופן דומה, אם באפליקציה יש אפשרויות ספציפיות למכשיר, לכל משתמש במכשיר יש הגדרות נפרדות, לכן SharedPreferences הוא פתרון לא אידיאלי.

PreferenceDataStore מאפשר להשתמש בקצה עורפי בהתאמה אישית של אחסון כדי לשמור ערכי Preference. לקבלת מידע נוסף ראו שימוש במאגר נתונים מותאם אישית.

קריאת הערכים של ההעדפות

כדי לאחזר את האובייקט SharedPreferences שנמצא בשימוש, קוראים לפונקציה PreferenceManager.getDefaultSharedPreferences(). השיטה הזו פועלת מכל מקום באפליקציה, אבל מומלץ ומפצלים את האפליקציה לשכבות. מידע נוסף זמין במאמר נתונים בשכבת זרימת הנתונים.

לדוגמה, בהינתן EditTextPreference עם מפתח של "signature", כמו ככה:

<EditTextPreference
        app:key="signature"
        app:title="Your signature"/>

אפשר לאחזר את הערך השמור של ה-Preference הזה באופן גלובלי, באופן הבא:

Kotlin

val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this /* Activity context */)
val name = sharedPreferences.getString("signature", "")

Java

SharedPreferences sharedPreferences =
        PreferenceManager.getDefaultSharedPreferences(this /* Activity context */);
String name = sharedPreferences.getString("signature", "");

האזנה לשינויים בערכי ההעדפות

כדי להאזין לשינויים בערכים של Preference, אפשר לבחור מבין שניים ממשקים:

בטבלה הבאה אפשר לראות את ההבדלים בין שני הממשקים:

OnPreferenceChangeListener OnSharedPreferenceChangeListener
מוגדר בPreference יחיד. חלה על כל Preference האובייקטים.
מתבצעת שיחה כאשר Preference עומד לשנות את הערך השמור שלו, גם אם הערך שבהמתנה זהה לערך שנשמר. מתבצעת שיחה רק כאשר הערך שנשמר עבור Preference משתנה.
התקשרו רק דרך ספריית Preference. חלק נפרד של האפליקציה יכולה לשנות את הערך שנשמר. תתבצע שיחה בכל פעם שהערך השמור משתנה, גם אם הוא מערך אחר חלק מהיישום.
בוצעה קריאה לפני שמירת הערך שבהמתנה. מתבצעת קריאה אחרי שמירת הערך.
התקשרת בזמן שימוש ב-SharedPreferences או ב- PreferenceDataStore. בוצעה שיחה רק כשמשתמשים בSharedPreferences.

הטמעת OnPreferenceChangeListener

הטמעה של OnPreferenceChangeListener מאפשרת לך להאזין לשינוי לערך של Preference. לאחר מכן אפשר לוודא שהשינוי מתרחשת. לדוגמה, הקוד הבא מראה איך להאזין לשינוי ערך של EditTextPreference עם מפתח של "name":

Kotlin

override fun onPreferenceChange(preference: Preference, newValue: Any): Boolean {
    Log.e("preference", "Pending Preference value is: $newValue")
    return true
}

Java

@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
    Log.e("preference", "Pending Preference value is: " + newValue);
    return true;
}

בשלב הבא צריך להגדיר את ה-listener הזה ישירות עם setOnPreferenceChangeListener() ככה:

Kotlin

preference.onPreferenceChangeListener = ...

Java

preference.setOnPreferenceChangeListener(...);

הטמעת OnSharedPreferenceChangeListener

כששומרים על ערכי Preference באמצעות SharedPreferences, אפשר גם להשתמש SharedPreferences.OnSharedPreferenceChangeListener כדי להאזין לשינויים. כך אפשר להאזין כשהערכים ששמורים על ידי Preference משתנים, למשל, במהלך סנכרון הגדרות עם שרת. הדוגמה הבאה מראה איך להקשיב לשינוי בערך של EditTextPreference עם מפתח של "name":

Kotlin

override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) {
    if (key == "signature") {
        Log.i(TAG, "Preference value was updated to: " + sharedPreferences.getString(key, ""))
    }
}

Java

@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
    if (key.equals("signature")) {
        Log.i(TAG, "Preference value was updated to: " + sharedPreferences.getString(key, ""));
    }
}

רישום המאזינים באמצעות registerOnSharedPreferenceChangedListener() ככה:

Kotlin

preferenceManager.sharedPreferences.registerOnSharedPreferenceChangeListener(...)

Java

getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(...);

Kotlin

    val listener: SharedPreferences.OnSharedPreferenceChangeListener =
            SharedPreferences.OnSharedPreferenceChangeListener {...}
    

Java

    SharedPreferences.OnSharedPreferenceChangeListener listener =
            new SharedPreferences.OnSharedPreferenceChangeListener() {...}
    

כדי לנהל כראוי את מחזור החיים ב-Activity או ב-Fragment, צריך לרשום ו ביטול הרישום של ה-listener הזה בקריאות החוזרות (callback) של onResume() ו-onPause(), כפי שמוצג בדוגמה הבאה:

Kotlin

override fun onResume() {
    super.onResume()
    preferenceManager.sharedPreferences.registerOnSharedPreferenceChangeListener(this)
}

override fun onPause() {
    super.onPause()
    preferenceManager.sharedPreferences.unregisterOnSharedPreferenceChangeListener(this)
}

Java

@Override
public void onResume() {
    super.onResume();
    getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}

@Override
public void onPause() {
    super.onPause();
    getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
}

שימוש במאגר נתונים בהתאמה אישית

למרות שמומלץ לשמור על ה-Preference אובייקטים באמצעות SharedPreferences, אפשר גם להשתמש במאגר נתונים בהתאמה אישית. מאגר נתונים בהתאמה אישית יכול להיות שימושי במקרים הבאים: שומרת ערכים למסד נתונים או שהערכים ספציפיים למכשיר, אפשר לראות בדוגמאות הבאות.

הטמעת מאגר הנתונים

כדי להטמיע מאגר נתונים בהתאמה אישית, צריך ליצור מחלקה שמרחיבה PreferenceDataStore הדוגמה הבאה יוצרת מאגר נתונים שמטפל String ערכים:

Kotlin

class DataStore : PreferenceDataStore() {
    override fun putString(key: String, value: String?) {
        // Save the value somewhere.
    }

    override fun getString(key: String, defValue: String?): String? {
        // Retrieve the value.
    }
}

Java

public class DataStore extends PreferenceDataStore {
    @Override
    public void putString(String key, @Nullable String value) {
        // Save the value somewhere.
    }
    @Override
    @Nullable
    public String getString(String key, @Nullable String defValue) {
        // Retrieve the value.
    }
}

כדי למנוע חסימה של המשתמש, כדאי להריץ פעולות שגוזלות זמן רב מהשרשור הראשי גרפי. מכיוון שיכול להיות שה-Fragment או Activity מכילים את שמאגר הנתונים יושמד תוך שמירה על ערך, מארגנים את הנתונים בצורה סריאלית, לא יאבדו ערכים שהמשתמש שינה.

הפעלת מאגר הנתונים

אחרי שמטמיעים את מאגר הנתונים, מגדירים את מאגר הנתונים החדש onCreatePreferences() כך ש-Preference אובייקטים ישמרו ערכים עם מאגר הנתונים במקום להשתמש בברירת המחדל SharedPreferences. אפשר להפעיל מאגר הנתונים של כל Preference או של כל ההיררכיה.

כדי להפעיל מאגר נתונים בהתאמה אישית עבור Preference ספציפי, צריך להתקשר setPreferenceDataStore() ב-Preference, כמו בדוגמה הבאה:

Kotlin

val preference: Preference? = findPreference("key")
preference?.preferenceDataStore = dataStore

Java

Preference preference = findPreference("key");
if (preference != null) {
    preference.setPreferenceDataStore(dataStore);
}

כדי להפעיל מאגר נתונים מותאם אישית להיררכיה שלמה, יש להפעיל את setPreferenceDataStore() ב-PreferenceManager:

Kotlin

val preferenceManager = preferenceManager
preferenceManager.preferenceDataStore = dataStore

Java

PreferenceManager preferenceManager = getPreferenceManager();
preferenceManager.setPreferenceDataStore(dataStore);

מאגר נתונים שמוגדר ל-Preference ספציפי מבטל כל מאגר נתונים שעומד מוגדר להיררכיה המתאימה. ברוב המקרים, צריך להגדיר מאגר נתונים ההיררכיה כולה.