ארכיטקטורת מידע

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

דוגמאות ומקור

רוב הדפים בהגדרות מוטמעים כרגע באמצעות המסגרת החדשה. דוגמה טובה היא DisplaySettings:‏packages/apps/Settings/src/com/android/settings/DisplaySettings.java

בהמשך מפורטים נתיבי הקבצים של רכיבים חשובים:

  • CategoryKey: packages/SettingsLib/src/com/android/settingslib/drawer/CategoryKey.java
  • DashboardFragmentRegistry: packages/apps/Settings/src/com/android/settings/dashboard/DashboardFragmentRegistry.java
  • DashboardFragment: packages/apps/Settings/src/com/android/settings/dashboard/DashboardFragment.java
  • AbstractPreferenceController: frameworks/base/packages/SettingsLib/src/com/android/settingslib/core/AbstractPreferenceController.java
  • BasePreferenceController (הושק ב-Android 9): packages/apps/Settings/src/com/android/settings/core/BasePreferenceController.java

הטמעה

יצרני המכשירים מומלצים להתאים את הארכיטקטורה הקיימת של המידע בהגדרות ולהוסיף דפי הגדרות לפי הצורך כדי להתאים לתכונות ספציפיות לשותפים. העברת העדפות מדף מדור קודם (הוטמע בתור SettingsPreferencePage) לדף חדש (הוטמע באמצעות DashboardFragment) יכול להיות מורכב. ההעדפה במהלך סביר להניח שדף מדור קודם לא מוטמע עם PreferenceController.

לכן, כשמעבירים העדפות מדף מדור קודם לדף חדש, צריך ליצור PreferenceController ומעבירים את הקוד לשלט רחוק לפני ליצור אותו ב-DashboardFragment החדש. ממשקי ה-API שנדרשים ל-PreferenceController מתוארים בשם שלהם ומתוועדים ב-Javadoc.

מומלץ מאוד להוסיף בדיקת יחידה לכל PreferenceController. אם השינוי נשלח ל-AOSP, צריך לבצע בדיקת יחידה. למידע נוסף על כתיבת בדיקות שמבוססות על Robolectric, תוכלו לעיין בקובץ readme‏ packages/apps/Settings/tests/robotests/README.md.

ארכיטקטורת מידע בסגנון פלאגין

כל פריט בהגדרות מיושם כ-Preference. אפשר להעביר בקלות העדפה מדף אחד לדף אחר.

כדי שיהיה קל יותר להעביר כמה הגדרות, ב-Android 8.0 הושק קטע מארח בסגנון פלאגין שמכיל את פריטי ההגדרות. הפריטים בהגדרות מוגדרים כבקרים בסגנון פלאגין. לכן, דף הגדרות מורכב מקטע מארח יחיד וממספר רכיבי בקרה של הגדרות.

קטע מרכז הבקרה

DashboardFragment הוא המארח של בקרי העדפות בסגנון פלאגין. החלק הקוד מקבל בירושה מ-PreferenceFragment ויש לו הוקס להרחבה ולעדכון של רשימות העדפות סטטיות ודינמיות.

העדפות סטטיות

רשימת העדפות סטטית מוגדרת ב-XML באמצעות התג <Preference>. בהטמעה של DashboardFragment, משתמשים בשיטה getPreferenceScreenResId() כדי להגדיר איזה קובץ XML מכיל את רשימת ההעדפות הסטטית שרוצים להציג.

העדפות דינמיות

פריט דינמי מייצג משבצת עם כוונה, שמובילה לנכס חיצוני או פנימי פעילות. בדרך כלל, הכוונה מובילה לדף הגדרות אחר. לדוגמה, פריט ההגדרה 'Google' בדף הבית של ההגדרות הוא פריט דינמי. פריטים דינמיים מוגדרים ב-AndroidManifest (כפי שמתואר בהמשך) ונטענים דרך FeatureProvider (המוגדרת כ- DashboardFeatureProvider).

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

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

כדי להגדיר פעילות כהגדרה דינמית:

  • כדי לסמן את הפעילות כהגדרה דינמית, מוסיפים לה מסנן Intent.
  • אומרים לאפליקציית ההגדרות לאיזו קטגוריה היא שייכת. הקטגוריה היא קבועה, הוגדרה ב-CategoryKey.
  • אופציונלי: מוסיפים טקסט סיכום כשהגדרה מוצגת.

הנה דוגמה מתוך אפליקציית ההגדרות עבור DisplaySettings.

<activity android:name="Settings$DisplaySettingsActivity"
                   android:label="@string/display_settings"
                   android:icon="@drawable/ic_settings_display">
             <!-- Mark the activity as a dynamic setting -->
              <intent-filter>
                     <action android:name="com.android.settings.action.IA_SETTINGS" />
              </intent-filter>
             <!-- Tell Settings app which category it belongs to -->
              <meta-data android:name="com.android.settings.category"
                     android:value="com.android.settings.category.ia.homepage" />
             <!-- Add a summary text when the setting is displayed -->
              <meta-data android:name="com.android.settings.summary"
                     android:resource="@string/display_dashboard_summary"/>
             </activity>

בזמן הרינדור, החלק יוצג עם בקשה לקבלת רשימת העדפות מ-XML סטטי ומהגדרות דינמיות שהוגדרו ב-AndroidManifest. בין שה-PreferenceController מוגדרים בקוד Java ובין שהם מוגדרים ב-XML, DashboardFragment מנהל את לוגיקת הטיפול בכל הגדרה באמצעות PreferenceController (כפי שמתואר בהמשך). ואז הם יופיעו תוצג בממשק המשתמש כרשימה מעורבת.

בקר העדפות

יש הבדלים בין ההטמעה של PreferenceController ב-Android 9 וב-Android 8.x, כפי שמתואר .

PreferenceController במהדורת Android 9

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

הממשק של PreferenceController מוגדר כך: BasePreferenceController. לדוגמה, הקוד ב-packages/apps/Settings/src/com/android/settings/core/ BasePreferenceController.java

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

ל-BasePreferenceController יש ממשקי API כמו getAvailabilityStatus(),‏ displayPreference(),‏ handlePreferenceTreeClicked(), וכו'. תיעוד מפורט של כל ממשק API נמצא בכיתה של הממשק.

הגבלה על ההטמעה של BasePreferenceController (ו מחלקות המשנה שלו, כמו TogglePreferenceController) הוא החתימה מסוג constructor חייבת להתאים לאחת מהאפשרויות הבאות:

  • public MyController(Context context, String key) {}
  • public MyController(Context context) {}

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

DashboardFragment שומרת רשימה של PreferenceController במסך. ב-onCreate() של הפלח, כל הבקרים מופעלים בשיטה getAvailabilityStatus(), ואם היא מחזירה true, מתבצעת הפעלה של displayPreference() כדי לעבד את הלוגיקה של התצוגה. getAvailabilityStatus() חשוב גם להגדיר לאילו פריטים המערכת תציג תוצאות במהלך החיפוש.

PreferenceController במהדורות של Android 8.x

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

בהתאם לאינטראקציות עם ההעדפות, הממשק של PreferenceController כולל ממשקי API isAvailable(), displayPreference(), handlePreferenceTreeClicked() וכו'. תוכלו למצוא תיעוד מפורט על כל API במחלקה של הממשק.

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

ב-DashboardFragment מופיעה רשימה של PreferenceControllers במסך. ב-onCreate() של החלק, כל הבקרים מופעלים לפונקציה isAvailable(), ואם היא מחזירה את הערך true, הפונקציה displayPreference() מופעלת כדי לעבד את הלוגיקה של התצוגה.

שימוש ב-DashboardFragment

העברת העדפה מדף א' לדף ב'

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

העברה סטטית ב-Android 9

  1. חיפוש קובצי ה-XML המועדפים לדף וליעד המקוריים הדף הזה. אפשר למצוא את המידע הזה בדף אמצעי תשלום אחד (getPreferenceScreenResId()).
  2. מסירים את ההעדפה מה-XML של הדף המקורי.
  3. מוסיפים את ההעדפה ל-XML של דף היעד.
  4. מסירים את PreferenceController של ההעדפה הזו מהטמעת Java של הדף המקורי. בדרך כלל הוא נמצא ב-createPreferenceControllers(). ייתכן שהבקר מוצהר ב- ישירות בפורמט XML.

    הערה: יכול להיות שההעדפה לא כוללת PreferenceController.

  5. יצירת מופע של PreferenceController בדף היעד createPreferenceControllers(). אם PreferenceController מוגדר ב-XML בדף הישן, מגדירים אותו ב-XML של הדף החדש גם כן.

העברה דינמית ב-Android 9

  1. בודקים לאיזו קטגוריה שייכים דף היעד והדף המקורי. אפשר אפשר למצוא את המידע הזה ב-DashboardFragmentRegistry.
  2. יש לפתוח את הקובץ AndroidManifest.xml שמכיל את ההגדרה שבחרת תצטרכו לזוז ולמצוא את הרשומה 'פעילות' שמייצגת את ההגדרה הזו.
  3. מגדירים את ערך המטא-נתונים של הפעילות בשדה com.android.settings.category למפתח הקטגוריה של הדף החדש.

מעבר סטטי בגרסאות Android 8.x

  1. מוצאים את קובצי ה-XML של ההעדפה לדף המקורי ולדף היעד.
  2. אפשר למצוא את המידע הזה בשיטה getPreferenceScreenResId() של הדף.
  3. מסירים את ההעדפה ב-XML של הדף המקורי.
  4. מוסיפים את ההעדפה ל-XML של דף היעד.
  5. מסירים את הערך PreferenceController של ההעדפה הזו בהטמעת Java של הדף המקורי. בדרך כלל הקוד הוא getPreferenceControllers()
  6. הערה: ייתכן שלהעדפה אין PreferenceController.

  7. יוצרים את PreferenceController ב-getPreferenceControllers() של דף היעד.

מעבר דינמי בגרסאות Android 8.x

  1. בודקים איזו קטגוריה מתארחת בדף המקורי ובדף היעד. המידע הזה מופיע ב-DashboardFragmentRegistry.
  2. פותחים את הקובץ AndroidManifest.xml שמכיל את ההגדרה שרוצים להעביר ומאתרים את הרשומה Activity שמייצגת את ההגדרה הזו.
  3. משנים את ערך המטא-נתונים של הפעילות עבור com.android.settings.category, הגדרת הערך של מפתח הקטגוריה של הדף החדש.

יצירת העדפה חדשה בדף

אם ההעדפה מופיעה באופן סטטי בקובץ ה-XML של ההעדפות של הדף המקורי, פועלים לפי התהליך הסטטי שמתואר בהמשך. אחרת, פועלים לפי התהליך הדינמי.

יצירת העדפה סטטית

  1. מוצאים את קובצי ה-XML המועדפים לדף. אפשר למצוא את המידע הזה. מהשיטה getPreferenceScreenResId() בדף.
  2. מוסיפים פריט Preference חדש ב-XML. חשוב לוודא שיש לו android:key ייחודי.
  3. מגדירים PreferenceController להעדפה הזו בשיטה getPreferenceControllers() של הדף.
    • ב-Android 8.x וב-Android 9 (אופציונלי), יוצרים מופע של PreferenceController עבור ההעדפה הזו ב-method‏ createPreferenceControllers() של הדף.

      אם ההעדפה הזו כבר הייתה קיימת במקומות אחרים, יכול להיות שכבר יש לה PreferenceController. אפשר להשתמש PreferenceController שוב בלי ליצור גרסת build חדשה.

    • החל מ-Android 9, אפשר להצהיר על PreferenceController ב-XML ליד ההעדפה. לדוגמה:
      <Preference
              android:key="reset_dashboard"
              android:title="@string/reset_dashboard_title"
              settings:controller="com.android.settings.system.ResetPreferenceController"/>

יצירת העדפה דינמית

  1. בודקים לאיזו קטגוריה שייכים דף היעד והדף המקורי. המידע הזה מופיע ב-DashboardFragmentRegistry.
  2. יצירת פעילות חדשה ב-AndroidManifest
  3. מוסיפים את המטא-נתונים הנדרשים לפעילות החדשה כדי להגדיר את ההגדרה. מגדירים את ערך המטא-נתונים של com.android.settings.category לאותו ערך שהוגדר בשלב 1.

דף חדש

  1. יצירת מקטע חדש בירושה מ-DashboardFragment.
  2. מגדירים את הקטגוריה שלו ב-DashboardFragmentRegistry.

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

  3. פועלים לפי השלבים להוספת ההגדרות הנדרשות לדף הזה. מידע נוסף זמין בקטע הטמעה.

אימות

  • מריצים את בדיקות Robolectric בהגדרות. כל הבדיקות הקיימות והחדשות אמורות לעבור.
  • יוצרים ומתקינים את ההגדרות, ואז פותחים באופן ידני את הדף שמשנים. הדף אמור להתעדכן באופן מיידי.