פעולות שונות במערכת Android יכולות להשפיע על המצב של החלק. כדי לוודא שהמצב של המשתמש נשמר, מסגרת Android שומרת ומשחזרת באופן אוטומטי את הקטעים ואת סטאק החזרה. לכן, צריך לוודא שגם הנתונים שבקטע השמור יישמרו ויוחזרו.
בטבלה הבאה מפורטות הפעולות שגורמות לאובדן המצב של המקטע, ובדיקה אם סוגי המצב השונים נשארים לאורך כל השינויים האלה. סוגי המצבים שצוינו בטבלה הם:
- משתנים: משתנים מקומיים בחלק.
- מצב התצוגה: כל נתון ששייך לתצוגה מפורטת אחת או יותר בקטע.
- SavedState: נתונים ייחודיים למופעי הפלח הזה שצריך לשמור ב-
onSaveInstanceState()
. - NonConfig: נתונים שנשלפו ממקור חיצוני, כמו שרת או מאגר מקומי, או נתונים שנוצרו על ידי משתמשים ונשלחים לשרת לאחר ביצוע ההתחייבות.
לרוב, המערכת מתייחסת ל-Variables כמו ל-SavedState, אבל בטבלה הבאה מוסבר ההבדל בין השניים כדי להמחיש את ההשפעה של הפעולות השונות על כל אחד מהם.
פעולה | משתנים | הצגת המצב | SavedState | NonConfig |
---|---|---|---|---|
הוספה לערימה הקודמת | ✓ | ✓ | x | ✓ |
שינוי בתצורה | x | ✓ | ✓ | ✓ |
תהליך מוות/פנאי | x | ✓ | ✓ | ✓* |
הוסר ולא נוסף לערימה הקודמת | x | x | x | x |
המארח הסתיים | x | x | x | x |
* אפשר לשמור על מצב NonConfig בכל מוות של תהליך באמצעות מודול המצב השמור ל-ViewModel.
טבלה 1: פעולות הרסניות שונות של מקטעים וההשפעות שיש להן על סוגי מצבים שונים.
נבחן דוגמה ספציפית. נניח שרוצים ליצור מסך שיוצר מחרוזת אקראית, מציג אותה ב-TextView
ומאפשר לערוך את המחרוזת לפני ששולחים אותה לחבר:
בדוגמה הזו, נניח שכאשר המשתמש לוחץ על לחצן העריכה, באפליקציה מוצגת תצוגה מסוג EditText
שבה המשתמש יכול לערוך את ההודעה. אם המשתמש ילחץ על ביטול, התצוגה EditText
אמורה להימחק ולהגדיר את החשיפה ל-View.GONE
. כדי להציג מסך כזה, יכול להיות שתצטרכו לנהל ארבעה פריטים של נתונים כדי להבטיח חוויה חלקה:
נתונים | סוג | סוג המדינה | תיאור |
---|---|---|---|
seed |
Long |
NonConfig | זרע שמשמש ליצירה אקראית של מעשה טוב חדש. נוצר כשה-ViewModel נוצר. |
randomGoodDeed |
String |
SavedState + משתנה | נוצר כשהקטע נוצר בפעם הראשונה.
randomGoodDeed נשמר כדי להבטיח שהמשתמשים יראו את אותו
מעשה טוב אקראי גם אחרי מוות אקראי
וחידוש. |
isEditing |
Boolean |
SavedState + משתנה | דגל בוליאני שמוגדר כ-true כשהמשתמש מתחיל לערוך.
isEditing נשמר כדי לוודא שחלק המסך שמשמש לעריכה יישאר גלוי כשהקטע ייווצר מחדש. |
טקסט ערוך | Editable |
הצגת המצב (בבעלות EditText ) |
הטקסט הערוך בתצוגה EditText .
התצוגה EditText שומרת את הטקסט הזה כדי לוודא שהשינויים שבוצעו על ידי המשתמש לא ייאבדו. |
טבלה 2: מצבים שאפליקציית היצירה של טקסט אקראי חייבת לנהל.
בקטעים הבאים מוסבר איך לנהל את מצב הנתונים בצורה נכונה באמצעות פעולות הרסניות.
הצגת המצב
התצוגות אחראיות לניהול המצב שלהן. לדוגמה, כשתצוגה מקבלת קלט ממשתמש, היא אחראית לשמור ולשחזר את הקלט הזה כדי לטפל בשינויים בהגדרות. לכל התצוגות הזמינות של framework של Android יש הטמעה משלה של onSaveInstanceState()
ו-onRestoreInstanceState()
, כך שלא צריך לנהל את מצב התצוגה בתוך המקטע.
לדוגמה, בתרחיש הקודם, המחרוזת הערוכה נשמרת ב-EditText
. ל-EditText
יש גישה לערך של הטקסט שהוא מציג, וגם לפרטים נוספים, כמו תחילת הטקסט שנבחר וסוף הטקסט שנבחר.
כדי לשמור את המצב של תצוגה, צריך להקצות לה מזהה. המזהה הזה חייב להיות ייחודי בתוך הקטע ובהיררכיית התצוגה שלו. תצוגות מפורטות ללא מזהה לא יכולות לשמור את המצב שלהן.
<EditText android:id="@+id/good_deed_edit_text" android:layout_width="match_parent" android:layout_height="wrap_content" />
כפי שצוין בטבלה 1, תצוגות שומרות ומשחזרות את ה-ViewState
שלהן באמצעות כל הפעולות שלא מסירות את המקטע או משמידים את המארח.
SavedState
הפלח אחראי לניהול כמויות קטנות של מצב דינמי שמהווה חלק בלתי נפרד מהאופן שבו הפלח פועל. אפשר לשמור נתונים שקל לסדר בסדרה באמצעות Fragment.onSaveInstanceState(Bundle)
.
בדומה ל-Activity.onSaveInstanceState(Bundle)
, הנתונים שמוסיפים לחבילה נשמרים במהלך שינויי תצורה, מוות של תהליך ויצירה מחדש של תהליך, והם זמינים בשיטות onCreate(Bundle)
, onCreateView(LayoutInflater, ViewGroup, Bundle)
ו-onViewCreated(View, Bundle)
של הקטע.
בהמשך לדוגמה הקודמת, randomGoodDeed
הוא המשטר שמוצג למשתמש, ו-isEditing
הוא דגל שקובע אם הקטע מציג או מסתיר את EditText
. צריך לשמור את המצב השמור באמצעות onSaveInstanceState(Bundle)
, כפי שמתואר בדוגמה הבאה:
Kotlin
override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) outState.putBoolean(IS_EDITING_KEY, isEditing) outState.putString(RANDOM_GOOD_DEED_KEY, randomGoodDeed) }
Java
@Override public void onSaveInstanceState(@NonNull Bundle outState) { super.onSaveInstanceState(outState); outState.putBoolean(IS_EDITING_KEY, isEditing); outState.putString(RANDOM_GOOD_DEED_KEY, randomGoodDeed); }
כדי לשחזר את המצב ב-onCreate(Bundle)
, מאחזרים את הערך המאוחסן מהחבילה:
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) isEditing = savedInstanceState?.getBoolean(IS_EDITING_KEY, false) randomGoodDeed = savedInstanceState?.getString(RANDOM_GOOD_DEED_KEY) ?: viewModel.generateRandomGoodDeed() }
Java
@Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (savedInstanceState != null) { isEditing = savedInstanceState.getBoolean(IS_EDITING_KEY, false); randomGoodDeed = savedInstanceState.getString(RANDOM_GOOD_DEED_KEY); } else { randomGoodDeed = viewModel.generateRandomGoodDeed(); } }
כמו שצוין בטבלה 1, חשוב לזכור שהמשתנים נשמרים כשמציבים את המקטע בסטאק העורפי. וההתייחסות אליהם כמצב שמור, מבטיחה שהם ימשיכו להתקיים בכל הפעולות ההרסניות.
NonConfig
צריך למקם נתונים שאינם נתוני תצורה מחוץ לפרמנט, למשל ב-ViewModel
. בדוגמה הקודמת שלמעלה, הערך seed
(המצב NonConfig) נוצר ב-ViewModel
.
הלוגיקה לשמירה על המצב שלו היא בבעלות ViewModel
.
Kotlin
public class RandomGoodDeedViewModel : ViewModel() { private val seed = ... // Generate the seed private fun generateRandomGoodDeed(): String { val goodDeed = ... // Generate a random good deed using the seed return goodDeed } }
Java
public class RandomGoodDeedViewModel extends ViewModel { private Long seed = ... // Generate the seed private String generateRandomGoodDeed() { String goodDeed = ... // Generate a random good deed using the seed return goodDeed; } }
הכיתה ViewModel
מאפשרת באופן מהותי לשמור נתונים אחרי שינויים בהגדרות, כמו סיבוב המסך, והם נשארים בזיכרון כשהקטע מועבר ל-back stack. אחרי מותו של התהליך והיצירה מחדש שלו, ה-ViewModel
נוצר מחדש ו-seed
חדש נוצר. הוספת מודול SavedState
ל-ViewModel
מאפשרת ל-ViewModel
לשמור מצב פשוט במהלך מוות ויצירה מחדש של התהליך.
מקורות מידע נוספים
למידע נוסף על ניהול מצב של קטעי קוד, תוכלו לעיין במקורות המידע הנוספים הבאים.
שיעורי Lab
- Codelab של רכיבים שמותאמים למחזור החיים