יום שבת, פברואר 5

איחסון נתונים: Shared Preferences חלק שני: Preferences Framework

הנה החלק השני בנושא "Shared Preferences". החלק הראשון הציג מנגנון  פשוט לשמירת פרמטרים  בפורמט של key/value.

החלק הזה יציג את ה-Preferences Framework, שכולל תוספת ווידגטים מיוחדים ב-UI לקביעת ושמירת ערכי הפרמטרים ב-Preferences. 


הווידגטים של - Preferences Framework אותם נכיר:

  1. CheckBoxPreference - מגדיר כפתור בחירה CheckBox. 
  2. EditTextPreference - מגדיר חלון EditText להכנסת טקסט חופשי.
  3.   ListPreference - הגדרת List כולל כפתורי בחירה. 
  4. RingtonePreference - בחירת מצב ה-rington.
הערה: בנוסף ל4 הווידגטים הנ"ל, קיים אחד נוסף, ה-DialogPreference, אך מנסיוני הוא אינו עובד (אשמח להערות בנושא). 
נכיר גם שני מאגדי קבוצות של ווידגטים, שמאפשרים בניית תצוגה היררכית של הווידגטים:
  1. PreferenceCategory - מאגד קבוצה של ווידגטים. הוא יוצר חציצה + כותרת בין הווידגטים המאוגדים בקטגוריה לבין הווידגטים שמופעים לפניהם. נדגים את זה כמובן.
  2. PreferenceScreen - מאגד קבוצה של ווידגטים ומציג אותם במסך נפרד. 

 בניית מסך ה-UI עבור ה-Preferences נעשה בתוך קובץ xml נפרד, שמכיל את 4 סוגי הווידגטים ושני סוגי המאגדים הנ"ל. נראה זאת בהמשך.

נעבור ישר לדוגמא, נתחיל בהצגת צילומי מסך של ה-UI:

המסך הראשי: שני כפתורי הפעלה+טקסט הסבר.




מסך ה-Preferences הראשי: שימו לב לחציצה+כותרת של ה-Category.  ה-category כאמור הוא ווידגט לחציצה.



התצוגה שהתקבלה בעיקבות לחיצה על האלמנט השני - EditText. מופיע ה-EditText ויידגט. הטקסט שיוקלד ישמר כמובן ב-Preferences:




התצוגה שהתקבלה בעקבות נגיעה בשורה השלישית במסך ה-Preferences ראשי, ה-ListPreferences 





לחיצה על כפתור ה- Show Preferences במסך הראשי: מופיע Toast Message שמציג את ערכי כל ששת הפרמטרים שהגדרנו:





נעבור לקוד.
התוכנית תומכת בשני מסכי תצוגה:
ה-Activity הראשי תומך במסך הראשי - ראה תמונה למעלה
ה- PreferencesEdit class שפורס ומציג את ה-Preferences UI.
הקבצים בהם נתעניין:
  1. PreferencesEdit.java: הקובץ שפורס את ה-UI של ה-Preferences. 
  2. Preferences.xml: קובץ ה-xml בו מוגדר ה-UI של ה-preferences.
  3.  array.xml: קובץ עזר  שמכיל פרמטרים של ה-ListPreferences
  4. PrefsFramework.java: ה-java עם ה-Activity הראשי - המסך הראשי.

הקובץ הראשון:  PreferencesEdit.java



import android.os.Bundle;
import android.preference.PreferenceActivity;


  1. public class PreferencesEdit extends PreferenceActivity {
  2. @Override
  3. public void onCreate(Bundle savedInstanceState) {
  4. super.onCreate(savedInstanceState);
  5. addPreferencesFromResource(R.xml.preferences);
  6. }
  7. }

קשה היה לצפות למשהו פחות מורכב מזה. 
שורה 1: extends PreferenceActivity. זהו ה-class אותו יש לרשת.
שורה 5: זוהי שורת המפתח, שפורסת את קובץ ה-xml אותו נציג מייד ומייצרת את ה-UI בהתאם.

הקובץ השני: preferences.xml.
הקובץ נמצא ב-/res/xml

מתאר את תצוגת הPreferences UI. ראינו למעלה את הפריסה שלו לתצוגה.

<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:title="Checkbox Category">
<CheckBoxPreference
android:key="checkbox1"
android:title="Checkbox Preference 1"
android:summary="Mark selection"
/>
</PreferenceCategory>
<PreferenceCategory android:title="EditTextPreference Category">
<EditTextPreference
android:key="editText"
android:title="Edit Text"
android:summary="Click to enter name"
android:dialogTitle="Insert Text"
android:dialogMessage="Dialog Message"
android:positiveButtonText="yes"
android:negativeButtonText="no"
/>
</PreferenceCategory>
<ListPreference
android:key="email"
android:title="ListPreference"
android:summary="Click to preferences list"
android:entries="@array/names"
android:entryValues="@array/emails"
android:dialogTitle="Select a name" />
<PreferenceCategory android:title="Rington Category">
<RingtonePreference
android:key="ringtone"
android:title="Ringtone Preference"
android:ringtoneType="alarm" 
android:positiveButtonText="yes"
android:showDefault="true"
android:summary="Select a ringtone"
/>
</PreferenceCategory>
<PreferenceScreen
android:key="prefscreen1"
android:title="PreferenceScreen"
android:summary="Click for another preferences screen">
<CheckBoxPreference
android:key="checkbox2"
android:title="Checkbox Preference 2"
android:summary="Mark selection"
/>
<CheckBoxPreference
android:key="checkbox3"
android:title="Checkbox Preference 3"
android:summary="Mark selection"
/>
</PreferenceScreen>

</PreferenceScreen>






נתעכב על ה-ListPreferences :
מדובר בווידגט המציג רשימת פרמטרים עם כפתורי רדיו, ראה צילום למעלה.

  1. <ListPreference
  2. android:key="email"
  3. android:title="ListPreference"
  4. android:summary="Click to preferences list"
  5. android:entries="@array/names"
  6. android:entryValues="@array/emails"
  7. android:dialogTitle="Select a name" />

שורה 2:  זהו ה-key של הפרמטר, לצורך שמירה ב- preferences. 
שורה 3: כותרת. ראה צילום מסך למעלה.
שורה 4: "טיפ" נוסף - ראה צילום מסך למעלה.
שורה 5: רשימת הפריטים שתופיע עם הנגיעה - ראה רשימת השמות למעלה (david, yosi, of, sela). הרשימה נמצאת בקובץ arrays.xml בספרית res/values.
שורה 6: רשימת הערכים שמתייחסת לרשימת הפריטים הנ"ל.נמצאת גם בקובץ arrays.xml .
שורה 7:  dialogTitle - הכותרת שתופיע מעל הרשימה - ראה צילום מסך למעלה.

הקובץ השלישי: arrays.xml שמכיל את שתי הרשימות עבור ה-ListPreferences.


<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="emails">
<item>"david@gmail.com"</item>
<item>yosi@walla.co.il</item>
<item>nof.yam@barak.net.il</item>
<item>sela@yahoo.com</item>
</string-array>
<string-array name="names">
<item>david</item>
<item>yosi</item>
<item>nof</item>
<item>sela</item>
</string-array>
</resources>

הרשימה הראשונה, מכילה את השמות  שיוצגו ב-dialog ( שורה 6 למעלה, entries) 
הרשימה השניה - names - מכילה את הערכים (שורה 7 למעלה).
בדוגמא הנ"ל, הערך שמוצמד לכל שם היא כתובת אימייל. זהו כמובן הערך שישמר בזיכרון. ראה צילום מסך - לחיצה על כפתור Show Preferences.


הקובץ הרביעי: ה-Activity הראשי.




import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

public class PrefsFramework extends Activity {
String checkbox; 
String editTextContent;
String list;
String ringtone; 
String checkbox2;
String checkbox3;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button buttonPrefsShow = (Button) findViewById(R.id.button_prefs_show); 
buttonPrefsShow.setOnClickListener(new OnClickListener(){
      public void onClick(final View v) {
      Context context = getApplicationContext();
      Toast.makeText(context, "checkbox ="+checkbox+
      "\ntext="+editTextContent+
      "\nlist="+list+
      "\nringtone="+ringtone+
      "\ncheckbox2="+checkbox2+
      "\ncheckbox2="+checkbox3
      , Toast.LENGTH_LONG).show();
      }
});
Button buttonPrefsSet = (Button) findViewById(R.id.button_prefs_set); 
buttonPrefsSet.setOnClickListener(new OnClickListener(){
      public void onClick(final View v) {
      Context context = getApplicationContext();
      Intent intentPrefsSet =  new Intent(context, PreferencesEdit.class);
      startActivity(intentPrefsSet);
      }
});
}
@Override
public void onResume() {
super.onResume();
SharedPreferences prefs=PreferenceManager.getDefaultSharedPreferences(this);
checkbox = new Boolean(prefs.getBoolean("checkbox1", false)).toString();
editTextContent = prefs.getString("editText", "<unset>");
list = prefs.getString("email", "<unset>");
ringtone = prefs.getString("ringtone", "<unset>");
checkbox2 = new Boolean(prefs.getBoolean("checkbox2", false)).toString();
checkbox3 = new Boolean(prefs.getBoolean("checkbox3", false)).toString();
}
}

ממומשות שתי מתודות:
onCreate: בתוכה מוגדרים ה-callbacksשל שני הכפתורים.
onResume: מופעלת כשחוזרים ממסך ה-Preferences UI. כאן נשלפים ששת פרמטרי ה-preferences מהזיכרון.


2 תגובות: