חלק מהגדרות המכשיר עשויות להשתנות בזמן שהאפליקציה פועלת. למשל, אך לא רק:
- גודל התצוגה של האפליקציה
- כיוון המסך
- גודל ומשקל הגופן
- שפה ואזור
- מצב כהה לעומת מצב בהיר
- זמינות המקלדת
רוב השינויים האלה בהגדרות האישיות מתרחשים בגלל אינטראקציות מסוימות של המשתמשים. עבור
לדוגמה, סיבוב או קיפול של המכשיר משנים את שטח המסך
זמינים לאפליקציה. באותו אופן, כשמשנים את הגדרות המכשיר כמו גודל הגופן
או העיצוב המועדף ישנו את הערכים המתאימים
אובייקט Configuration
.
בדרך כלל, הפרמטרים האלה מחייבים שינויים גדולים מספיק בממשק המשתמש של האפליקציה
שלפלטפורמת Android יש מנגנון ייעודי לביצוע שינויים.
המנגנון הזה הוא יצירה מחדש של Activity
.
פעילות פנאי
המערכת יוצרת מחדש Activity
כאשר מתרחש שינוי בהגדרות. כדי לעשות את זה,
קוראת ל-onDestroy()
ומשמידת את המכונה Activity
הקיימת. לאחר מכן
יוצרת מופע חדש באמצעות onCreate()
, והמופע החדש של Activity
אותחל עם ההגדרות האישיות המעודכנות. המשמעות היא גם שהמערכת
גם יוצר מחדש את ממשק המשתמש עם ההגדרות האישיות החדשות.
התנהגות ההפעלה עוזרת לאפליקציה להסתגל לתצורות חדשות על ידי טעינה מחדש אוטומטית של האפליקציה שלך עם משאבים חלופיים מתאימים את התצורה החדשה של המכשיר.
דוגמה לפעילויות בילוי
כדאי לשקול TextView
שמציג כותרת סטטית באמצעות
android:text="@string/title"
, כפי שמוגדר בקובץ XML לפריסה. כשהתצוגה
נוצר, הוא מגדיר את הטקסט פעם אחת בלבד, בהתאם לשפה הנוכחית. אם
השפה משתנה, המערכת יוצרת מחדש את הפעילות. לכן המערכת
גם יוצר מחדש את התצוגה ומאתחל אותה לערך הנכון על סמך
בשפת היעד.
המשחק גם מוחק כל מצב שנשמר כשדות
Activity
או בכל אחד מהאובייקטים Fragment
, View
או אובייקטים אחרים שהוא מכיל. הזה
היא כי יצירה מחדש של Activity
יוצרת מופע חדש לגמרי של Activity
וגם בממשק המשתמש. בנוסף, Activity
הישן כבר לא גלוי או בתוקף, לכן
שאר ההפניות אליו או לאובייקטים הכלולים בו לא פעילים. הן עלולות לגרום
באגים, דליפות זיכרון וקריסות.
הציפיות של המשתמשים
המשתמש באפליקציה מצפה שהמצב יישמר. אם משתמש ממלא טופס ופותח אפליקציה אחרת במצב ריבוי חלונות כדי להפנות למידע, עלולים לפגוע בחוויית המשתמש אם הם חוזרים לטופס שהניקוי שלו טופל או במקום אחר לגמרי באפליקציה. כמפתחים, חובה לספק חוויית משתמש עקבית באמצעות שינויי הגדרות אישיות ויצירה מחדש של פעילויות.
כדי לבדוק אם המצב נשמר באפליקציה, אפשר לבצע את הפעולות הבאות: פעולות שגורמות לשינויי הגדרות גם כשהאפליקציה בחזית וגם בזמן שהיא ברקע. פעולות אלה כוללות:
- מתבצע סיבוב של המכשיר
- כניסה למצב ריבוי חלונות
- שינוי גודל האפליקציה במצב ריבוי חלונות או בחלון חופשי
- קיפול מכשיר מתקפל עם מספר מסכים
- שינוי העיצוב של המערכת, למשל מצב כהה לעומת מצב בהיר
- שינוי גודל הגופן
- שינוי שפת המערכת או האפליקציה
- חיבור או ניתוק של מקלדת חומרה
- חיבור או ניתוק של אביזר עגינה
יש שלוש גישות מרכזיות שאפשר לבצע כדי לשמר את המצב הרלוונטי באמצעות
שחזור אחד (Activity
). באיזה אופן להשתמש תלוי בסוג המדינה שבה רוצים להשתמש
שמירה:
- עקביות מקומית לטיפול במוות של תהליכים עבור נתונים מורכבים או גדולים.
האחסון המקומי הקבוע כולל מסדי נתונים או
DataStore
. - אובייקטים שנשמרו, כמו מכונות של
ViewModel
לטיפול במצב שקשור לממשק המשתמש, הזיכרון בזמן שהמשתמש משתמש באפליקציה באופן פעיל. - מצב המכונה השמורה כדי לטפל במוות של תהליך ביוזמת המערכת ולשמור על מצב זמני שתלוי בקלט או בניווט של המשתמשים.
כדי לקרוא בפירוט על ממשקי ה-API של כל אחד מהנושאים האלה: וכאשר משתמשים בכל אחד מהמצבים האלה מתאים, ראו שמירת מצבים בממשק המשתמש.
הגבלת הפעילות הגופנית
אפשר למנוע שחזור אוטומטי של פעילויות בעקבות שינויים מסוימים בהגדרות.
פעולת היצירה של Activity
תוביל ליצירה מחדש של כל ממשק המשתמש, ושל כל האובייקטים שנגזרים
מActivity
. יש לך סיבות טובות להימנע מכך. עבור
לדוגמה, ייתכן שהאפליקציה לא תצטרך לעדכן משאבים במהלך
הגדרה אישית שונה, או שאולי חלה הגבלת ביצועים. במקרה הזה,
ניתן להצהיר שהפעילות שלכם מטפלת בשינוי ההגדרות האישיות עצמה
למנוע מהמערכת להפעיל מחדש את הפעילות.
כדי להשבית יצירה מחדש של פעילות במקרה של שינויים מסוימים בהגדרות האישיות,
צריך להוסיף את סוג ההגדרה אל android:configChanges
בקטע
רשומה <activity>
בקובץ AndroidManifest.xml
שלך. ערכים אפשריים מופיעים בעמודה
עבור המאפיין android:configChanges
.
קוד המניפסט הבא משבית את היצירה של Activity
עבור MyActivity
כאשר
שינוי כיוון המסך והזמינות של המקלדת:
<activity
android:name=".MyActivity"
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
android:label="@string/app_name">
שינויים מסוימים בהגדרות תמיד יגרמו להפעלה מחדש של הפעילות. לא ניתן להשבית אותם. לדוגמה, לא ניתן להשבית את שינוי הצבעים הדינמיים הושקה ב-Android 12L (רמת API 32).
תגובה לשינויים בתצורה במערכת התצוגה
במערכת View
, כשמתרחש שינוי תצורה שעבורו יש לך
בילוי של Activity
מושבת, הפעילות מקבלת קריאה אל
Activity.onConfigurationChanged()
. כל התצוגות המצורפות מקבלות גם
קריאה ל-View.onConfigurationChanged()
. כדי לבצע שינויים בהגדרות האישיות
לא נוספו אל android:configChanges
, המערכת יוצרת מחדש את הפעילות
כרגיל.
שיטת הקריאה החוזרת onConfigurationChanged()
מקבלת
אובייקט Configuration
שמציין את ההגדרה החדשה של המכשיר. נקראו
השדות באובייקט Configuration
כדי לקבוע מה
ההגדרה האישית. כדי לבצע את השינויים הבאים, צריך לעדכן את המשאבים
שבהם אתם משתמשים בממשק. כשהמערכת קוראת לשיטה הזו,
אובייקט Resources
מעודכן כדי להחזיר משאבים על סמך
הגדרה אישית. כך אפשר לאפס רכיבים בממשק המשתמש בלי המערכת
מתבצעת הפעלה מחדש של הפעילות.
לדוגמה, בדיקות ההטמעה הבאות של onConfigurationChanged()
האם המקלדת זמינה:
Kotlin
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
// Checks whether a keyboard is available
if (newConfig.keyboardHidden === Configuration.KEYBOARDHIDDEN_YES) {
Toast.makeText(this, "Keyboard available", Toast.LENGTH_SHORT).show()
} else if (newConfig.keyboardHidden === Configuration.KEYBOARDHIDDEN_NO) {
Toast.makeText(this, "No keyboard", Toast.LENGTH_SHORT).show()
}
}
Java
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Checks whether a keyboard is available
if (newConfig.keyboardHidden == Configuration.KEYBOARDHIDDEN_YES) {
Toast.makeText(this, "Keyboard available", Toast.LENGTH_SHORT).show();
} else if (newConfig.keyboardHidden == Configuration.KEYBOARDHIDDEN_NO){
Toast.makeText(this, "No keyboard", Toast.LENGTH_SHORT).show();
}
}
אם לא צריך לעדכן את האפליקציה על סמך ההגדרות האלה
שלך, אפשר במקום זאת לא להטמיע את onConfigurationChanged()
. כאן
כל המשאבים ששימשו לפני השינוי בהגדרה עדיין נמצאים בשימוש,
ורק נמנעתם מהפעלה מחדש של הפעילות. לדוגמה, אפליקציה לטלוויזיה
ייתכן שלא ירצו להגיב כאשר מקלדת Bluetooth מחוברת או מנותקת.
שמירת מצב
כשמשתמשים בשיטה הזו, עדיין צריך לשמור על המצב במהלך במחזור החיים של הפעילות. הסיבות לכך הן:
- שינויים בלתי נמנעים: שינויי תצורה שאי אפשר למנוע יכולים להפעיל מחדש את האפליקציה.
- מוות של תהליך: האפליקציה חייבת להיות מסוגלת לטפל ביוזמת המערכת עד לסיום תהליך המוות. אם המשתמש עוזב את האפליקציה והאפליקציה עוברת אל ברקע, המערכת עלולה להרוס את האפליקציה.
תגובה לשינויים בהגדרות ב-Jetpack פיתוח נייטיב
בעזרת Jetpack Compose, האפליקציה תוכל להגיב בקלות רבה יותר לשינויים בהגדרות.
עם זאת, אם משביתים יצירה מחדש של Activity
לכל שינויי ההגדרות שבהם הוא נמצא
כדי לעשות זאת, האפליקציה עדיין צריכה לטפל כראוי
שינויים בתצורה.
האובייקט Configuration
זמין בהיררכיה של ממשק המשתמש של הכתיבה
את היצירה המקומית LocalConfiguration
. בכל פעם שהוא משתנה,
פונקציות קומפוזביליות שקוראות מ-LocalConfiguration.current
יוצרות מחדש. עבור
למידע על אופן הפעולה של לוקאלים מקומיים, ראו היקף מקומי
עם CompositionLocal.
דוגמה
בדוגמה הבאה, תוכן קומפוזבילי מציג תאריך עם פורמט ספציפי.
התוכן הקומפוזבילי מגיב לשינויים בהגדרות הלוקאל של המערכת באמצעות קריאה
ConfigurationCompat.getLocales()
עם LocalConfiguration.current
.
@Composable
fun DateText(year: Int, dayOfYear: Int) {
val dateTimeFormatter = DateTimeFormatter.ofPattern(
"MMM dd",
ConfigurationCompat.getLocales(LocalConfiguration.current)[0]
)
Text(
dateTimeFormatter.format(LocalDate.ofYearDay(year, dayOfYear))
)
}
כדי להימנע מהפעלה מחדש של Activity
כשהלוקאל משתנה, ה-Activity
מארח את
כדי לכתוב את הקוד צריך לבטל את ההסכמה לשינויים בהגדרות הלוקאל. כדי לעשות את זה,
להגדיר את android:configChanges
להיות locale|layoutDirection
.
שינויים בהגדרות: מושגי מפתח ושיטות מומלצות
אלו המושגים המרכזיים שצריך להכיר כשעובדים על הגדרות אישיות שינויים:
- הגדרות: תצורות המכשיר קובעות את האופן שבו ממשק המשתמש יוצג המשתמש, למשל גודל התצוגה של האפליקציה, האזור או העיצוב של המערכת.
- שינויים בהגדרות: ההגדרות משתנות בעקבות אינטראקציה של המשתמשים. עבור למשל, המשתמש עשוי לשנות את הגדרות המכשיר או את האופן שבו הם מבצעים אינטראקציה פיזית באמצעות המכשיר. אין דרך למנוע שינויים בתצורה.
- הפעלה מחדש של
Activity
: שינויים בהגדרות יגרמו להפעלה מחדש שלActivity
כברירת מחדל. זהו מנגנון מובנה לאתחול מחדש של מצב האפליקציה של ההגדרה החדשה. - השמדה של
Activity
: שיבוש מסוגActivity
גורם למערכת להרוס את הישן שלActivity
וליצור מכונה חדשה במקומו. המופע הישן הוא מיושנות. כל שאר ההפניות אליו יובילו לדליפות זיכרון, באגים או קריסות. - מצב: מצב במכונה הישנה
Activity
לא נמצא במכונה החדשה. במופעActivity
, כי אלה שני מופעי אובייקטים שונים. שימור האפליקציה והמצב של המשתמש, כפי שמתואר במאמר מצבי שמירת ממשק המשתמש. - ביטול הסכמה: ביטול ההסכמה לשימוש מחודש בפעילות מסוג מסוים היא אופטימיזציה פוטנציאלית. לשם כך נדרשת האפליקציה מתעדכנת כראוי בתגובה לתצורה החדשה.
כדי לספק חוויית משתמש טובה, חשוב לפעול לפי השיטות המומלצות הבאות:
- להתכונן לשינויים תכופים בהגדרות: אל תניח ששינויי הגדרות אישיות נדירות או אף פעם לא קורים, בלי קשר לרמת ה-API, לגורם הצורה או לערכת הכלים לבניית ממשק משתמש. כשמשתמש גורם לשינוי בתצורה, הוא מצפה שאפליקציות יתעדכנו ימשיכו לפעול בצורה תקינה עם התצורה החדשה.
- מצב שימור: לא מאבדים את מצב המשתמש במהלך יצירה מחדש של
Activity
מתרחשת. משמרים את המצב כפי שמתואר במצבי שמירת ממשק המשתמש. - לא לבטל את ההסכמה כתיקון מהיר: אין לבטל את ההסכמה לשימוש מחודש ב-
Activity
. כקיצור דרך למניעת אובדן מצב. כדי להפסיק להשתמש בפעילות פנאי, לעמוד בהבטחה לטיפול בשינוי, ועדיין עלולים לאבד את מצב בגלל הפעלה מחדש שלActivity
משינויים אחרים בהגדרות, תהליך או לסגור את האפליקציה. אי אפשר להשבית לגמרי אתActivity
בילוי. משמרים את המצב כפי שמתואר במצבי שמירת ממשק המשתמש. - לא להימנע משינויי הגדרות: אין הגבלות על הכיוון,
יחס גובה-רוחב או יכולת שינוי, כדי למנוע שינויים בתצורה
Activity
. זה משפיע לרעה על משתמשים שרוצים להשתמש באפליקציה שלך בדרך המועדפת עליהם.
טיפול בשינויי הגדרות שמבוססים על גודל
שינויים בהגדרות מבוססות גודל יכולים להתרחש בכל שלב, ויש סבירות גבוהה יותר כשהאפליקציה שלך פועלת במכשיר במסך גדול שבו משתמשים יכולים להיכנס מצב ריבוי חלונות. הם מצפים שהאפליקציה תפעל כמו שצריך הסביבה.
יש שני סוגים כלליים של שינויים בגודל: שינויים משמעותיים זניח. שינוי משמעותי בגודל הוא מצב שבו קבוצה אחרת של רכיבים משאבים חלופיים חלים על ההגדרה החדשה עקב הבדל גודל המסך, כמו הרוחב, הגובה או הרוחב הקטן ביותר. במקורות המידע האלה אפשר למצוא: את אלו שהאפליקציה מגדירה את עצמה וגם את אלה מכל הספריות שלה.
הגבלת האפשרות ליצור מחדש את הפעילות במקרה של שינויי הגדרות שמבוססים על גודל
כאשר משביתים יצירה מחדש של Activity
לשינויי הגדרות מבוססי-גודל,
המערכת לא יוצרת מחדש את Activity
. במקום זאת, הוא מקבל שיחה אל
Activity.onConfigurationChanged()
כל התצוגות המצורפות מקבלות קריאה אל
View.onConfigurationChanged()
יצירה מחדש של Activity
מושבתת במקרה של שינויים בהגדרות מבוססות-גודל, כאשר
יש לך
android:configChanges="screenSize|smallestScreenSize|orientation|screenLayout
אינץ'
בקובץ המניפסט.
אפשר ליצור מחדש פעילות במקרה של שינויי הגדרה המבוססים על גודל
ב-Android 7.0 (רמת API 24) ואילך, האפשרות ליצור מחדש ב-Activity
רק ומתבססת על גודל
ישתנו אם השינוי משמעותי. כאשר המערכת לא
תיצור מחדש Activity
בגלל גודל לא מספיק, המערכת עלולה לקרוא
Activity.onConfigurationChanged()
וגם
View.onConfigurationChanged()
במקום זאת.
יש כמה נקודות שכדאי לשים לב אליהן לגבי Activity
ו-View
קריאות חוזרות (callback) ללא יצירה מחדש של Activity
:
- ב-Android 11 (רמת API 30) עד Android 13 (רמת API 33),
לא ניתן להתקשר אל
Activity.onConfigurationChanged()
. - יש בעיה ידועה שבה ייתכן ש-
View.onConfigurationChanged()
לא שנקראה במקרים מסוימים ב-Android 12L (רמת API 32) ובגרסאות מוקדמות של Android 13 (רמת API 33). מידע נוסף זמין במאמר בנושא הבעיה הציבורית הזו. הבעיה הזו טופלה מאז בגרסאות מאוחרות יותר של Android 13 וב-Android 14.
לקוד שתלוי בהאזנה לתצורה מבוססת-גודל
שינויים, מומלץ להשתמש בכלי עזר View
עם שינוי שבוטל
View.onConfigurationChanged()
במקום להסתמך על Activity
בילויים או
Activity.onConfigurationChanged()