Android Kotlin Fundamentals 04.1: מחזורי חיים והתחברות

Lab Lab זה הוא חלק מקורס Android Kotlin Fundamentals. כדי להפיק את המקסימום מהקורס הזה, יש לפעול ברצף לפי קודי שיעור ה-Lab. כל שיעורי Lab של הקורסים מופיעים בדף הנחיתה של Lab Kotlin Fundamentals ל-Android Lab.

מבוא

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

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

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

מה כבר צריך לדעת

  • מהי פעילות ואיך ליצור פעילות באפליקציה.
  • מה השיטה 'onCreate()' וסוג הפעולות המבוצעות בשיטה זו.
  • איך ליצור פריסות XML עבור הפעילות שלכם, ואיך לעדכן פריסה בזמן ריצה.

מה תלמדו

  • כיצד להדפיס פרטי רישום ביומן (לפעמים נקראים מסוף Android או צג Android).
  • היסודות של מחזורי החיים של Activity ו-Fragment, וקריאות חוזרות (callback) שמופעלות כשהפעילות זזה בין מדינות.
  • איך אפשר לבטל את השיטות לקריאה חוזרת (callback) של מחזור חיים כדי לבצע פעולות בזמנים שונים במחזור החיים של הפעילות.
  • איך להשתמש בספרייה של Timber כדי להתחבר באפליקציה.

מה תעשו

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

ב-Codelab הזה אתם עובדים עם אפליקציה למתחילים שנקראת DessertClicker. באפליקציה הזו, בכל פעם שהמשתמש מקיש על קינוח במסך, האפליקציה "רכישות" קינוח של המשתמש. האפליקציה מעדכנת ערכים בפריסה לגבי מספר הקינוחים שנרכשו והסכום הכולל שהמשתמש הוציא.

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

כל פעילות וכל שבר מכילים את מה שמכונה מחזור חיים. מדובר ברמז למחזור חיים של בעלי חיים, כמו מחזור החיים של הפרפר הזה – המצבים השונים של הפרפר מראים את הצמיחה שלו מלידה ועד למבוגרים בלבד.

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

לעתים קרובות ברצונך לשנות התנהגות מסוימת, או להפעיל קוד כלשהו כאשר המצב 'מחזור חיים' משתנה. לכן, מחלקת Activity עצמה וכל סיווגי המשנה של Activity, כמו AppCompatActivity, מיישמים קבוצה של שיטות התקשרות חזרה במחזור החיים. Android מפעיל קריאה חוזרת זו כאשר הפעילות עוברת ממצב אחד למצב אחר, ואתם יכולים לשנות את השיטות האלה בפעילויות שלכם כדי לבצע משימות בתגובה לשינויים האלה במחזור החיים. בתרשים הבא מוצגים המצבים במחזור החיים, לצד קריאה חוזרת (callbacks) זמינה לביטול.

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

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

שלב 1: בדיקת שיטת onCreate() והוספת הרישום

כדי להבין מה קורה במחזור החיים של Android, כדאי לדעת מתי קוראים לשיטות השונות של מחזור החיים. כך תוכלו לזהות בקלות מה השתבש ב-DessertClicker.

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

  1. מורידים את The DessertClicker Starter ופותחים אותה ב-Android Studio.
  2. הידור והפעלת האפליקציה, והקש כמה פעמים על תמונת הקינוח. לתשומת ליבכם, הערך של קינוחים שנמכרו והסכום הכולל של שקלים משתנים.
  3. יש לפתוח את MainActivity.kt ולבחון את שיטת onCreate() לפעילות זו
override fun onCreate(savedInstanceState: Bundle?) {
...
}

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

השיטה של מחזור החיים של onCreate() נקראת פעם אחת, מיד אחרי האתחול של הפעילות (כשאובייקט Activity החדש נוצר בזיכרון). לאחר ביצוע הonCreate(), הפעילות תיחשב כנוצרה.

  1. בשיטה onCreate(), מיד אחרי השיחה אל super.onCreate(), מוסיפים את השורה הבאה. אם צריך, מייבאים את הכיתה Log. (מקישים על Alt+Enter או על Option+Enter ב-Mac ובוחרים באפשרות ייבוא.)
Log.i("MainActivity", "onCreate Called")

הכיתה Log כותבת הודעות ל-Logcat. פקודה זו כוללת שלושה חלקים:

  • החומרה של הודעת היומן, כלומר, מידת החשיבות של ההודעה. במקרה זה, השיטה Log.i() כותבת הודעת מידע. שיטות אחרות בכיתה Log כוללות את Log.e() לשגיאות או Log.w() לאזהרות.
  • במקרה כזה, התג הוא היומן "MainActivity". התג הוא מחרוזת שמאפשרת לכם למצוא בקלות את ההודעות ביומן ב-Logcat. התג הוא בדרך כלל שם הכיתה.
  • ההודעה בפועל, מחרוזת קצרה, במקרה זה היא "onCreate called".
  1. הידור והפעלה של אפליקציית DessertClicker. לא ניתן לראות הבדלים בהתנהגות באפליקציה כשמקישים על הקינוח. ב-Android Studio, לוחצים על הכרטיסייה Logat בתחתית המסך.



    ה-Logcat הוא המסוף לרישום הודעות. כאן מופיעות הודעות מ-Android לגבי האפליקציה שלך, כולל ההודעות שנשלחו ישירות ליומן באמצעות השיטה Log.i() או שיטות כיתה אחרות של Log.
  2. בחלונית Logcat , מקלידים I/MainActivity בשדה החיפוש.


    ה-Logcat יכול לכלול הודעות רבות, שרובן לא מועילות לכם. ניתן לסנן את רשומות Logcat בדרכים רבות, אבל החיפוש הוא האפשרות הקלה ביותר. מכיוון שהשתמשת ב-MainActivity כתג היומן בקוד שלך, אפשר להשתמש בתג הזה כדי לסנן את היומן. הוספת I/ בהתחלה היא הודעת מידע שנוצרה על ידי Log.i().

    הודעת היומן כוללת את התאריך והשעה, את שם החבילה (com.example.android.dessertclicker), את תג היומן (עם I/ בהתחלה) ואת ההודעה עצמה. מכיוון שההודעה הזו מופיעה ביומן, את יודעת ש-onCreate() הוצא להורג.

שלב 2: מטמיעים את שיטת onStart()

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

חשוב לשים לב ש-onStart() מותאם לשיטת מחזור חיים מתאימה של onStop(). אם המשתמש מפעיל את האפליקציה ואז חוזר למסך הבית של המכשיר, הפעילות מופסקת והוא לא מוצג יותר במסך.

  1. ב-Android Studio, כשMainActivity.kt פתוח, בוחרים באפשרות Code > עקיפת שיטות או מקישים על Control+o. תופיע תיבת דו-שיח עם רשימה עצומה של כל השיטות שניתן לעקוף בכיתה הזו.
  2. התחילו להזין את onStart כדי לחפש את השיטה הנכונה. כדי לגלול לפריט התואם הבא, משתמשים בחץ למטה. בוחרים באפשרות onStart() ברשימה ולוחצים על OK (הוספה) כדי להוסיף את קוד הביטול של תבנית ההפרדה. הקוד נראה כך:
override fun onStart() {
   super.onStart()
}
  1. בתוך השיטה onStart(), מוסיפים הודעת יומן:
override fun onStart() {
   super.onStart()

   Log.i("MainActivity", "onStart Called")
}
  1. הידור והפעלה של אפליקציית DessertClicker, ופותחים את החלונית Logcat . מקלידים I/MainActivity בשדה החיפוש כדי לסנן את היומן. חשוב לשים לב שהשיטה onCreate() והשיטה onStart() נקראו זו אחר זו, ושהפעילות שלך גלויה במסך.
  2. לוחצים על הלחצן 'דף הבית' במכשיר, ולאחר מכן משתמשים במסך של השיחות האחרונות כדי לחזור לפעילות. חשוב לדעת שהפעילות חוזרת מהמקום שבו היא הפסיקה, עם כל הערכים האלה, וש-onStart() מתועדת שוב ל-Logcat. חשוב לשים לב שהשיטה onCreate() בדרך כלל לא נשלחת שוב.

במשימה הזו, תהיה לך אפשרות לשנות את האפליקציה ולהשתמש בספריית יומנים פופולרית שנקראת Timber. ל-Timber יש כמה יתרונות על פני סיווג ה-Log המובנה של Android. ובפרט, הספרייה Timber:

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

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

שלב 1: הוספת עץ לגרם

  1. נכנסים לקישור הזה אל פרויקט העץ ב-GitHub ומעתיקים את שורת הקוד מתחת לכותרת הורדה שמתחילה במילה implementation. שורת הקוד תיראה בערך כך, אם כי מספר הגרסה עשוי להיות שונה.
implementation 'com.jakewharton.timber:timber:4.7.1'
  1. ב-Android Studio, בתצוגה 'פרויקט: תצוגה של Android', מרחיבים את האפשרות Grale Scripts ופותחים את הקובץ build.gradle (מודול: אפליקציה).
  2. בקטע התלויות, מדביקים את שורת הקוד שהעתקת.
dependencies {
   ...
   implementation 'com.jakewharton.timber:timber:4.7.1'
}
  1. לוחצים על הקישור Sync now (סנכרון) בפינה השמאלית העליונה של Android Studio כדי לבנות מחדש את Gradle. גרסת ה-build צריכה להתבצע ללא שגיאות.

שלב 2: יצירת סיווג לאפליקציה ואתחול עץ

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

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

אחרי שיוצרים את הכיתה Application, יש לציין את הכיתה במניפסט של Android.

  1. בחבילה של dessertclicker, יש ליצור כיתה חדשה מ-Kotlin שנקראת ClickerApplication. כדי לעשות זאת, מרחיבים את app > Java ולוחצים לחיצה ימנית על com.example.android.dessertclicker. בוחרים באפשרות &gt חדש; קובץ Kotlin/Class.
  2. נותנים שם למחלקה ClickerApplication ומגדירים את הסוג ל-Class. לוחצים על אישור.

Android Studio יוצר מחלקה חדשה ב-ClickerApplication ופותחים אותה בעורך הקוד. הקוד נראה כך:

package com.example.android.dessertclicker

class ClickerApplication {
}
  1. אפשר לשנות את הגדרת הכיתה לסיווג משנה של Application, ולייבא את הסיווג של Application לפי הצורך.
class ClickerApplication : Application() {
  1. כדי לעקוף את השיטה onCreate(), בוחרים באפשרות Code > עקיפת שיטות או מקישים על Control+o.
class ClickerApplication : Application() {
   override fun onCreate() {
       super.onCreate()
   }
}
  1. בתוך השיטה onCreate(), מפעילים את הספרייה של Timber:
override fun onCreate() {
    super.onCreate()

    Timber.plant(Timber.DebugTree())
}

שורת הקוד הזו מפעילה את הספרייה של Timber עבור האפליקציה, כך שניתן יהיה להשתמש בספרייה בפעילויות שלך.

  1. פותחים את AndroidManifest.xml.
  2. בחלק העליון של האלמנט <application>, מוסיפים מאפיין חדש למחלקה ClickerApplication, כדי ש-Android ידע להשתמש בכיתה Application במקום במאפיין ברירת המחדל.
<application
   android:name=".ClickerApplication"
...

שלב 3: הוספת הצהרות ביומן של עץ

בשלב זה משנים את הקריאות ל-Log.i() כך שישתמשו ב-Timber, ואז מטמיעים רישום בכל השיטות האחרות של מחזור החיים.

  1. פותחים את MainActivity וגוללים אל onCreate(). יש להחליף את Log.i() ב-Timber.i() ולהסיר את תג היומן.
Timber.i("onCreate called")

כמו הכיתה Log, גם Timber משתמש בשיטה i() להודעות מידע. לתשומת ליבך, עם Timber אין צורך להוסיף תג יומן. מערכת Timber משתמשת באופן אוטומטי בשם של הכיתה כתג היומן.

  1. באופן דומה, יש לשנות את השיחה מסוג Log בonStart():
override fun onStart() {
   super.onStart()

   Timber.i("onStart Called")
}
  1. הידור והפעלה של אפליקציית DessertClicker ופותחים את Logcat. חשוב לזכור שעדיין מוצגות אותן הודעות יומן ב-onCreate() וב-onStart(), אבל רק Timberיצירת ההודעות האלה מתבצעת עכשיו, ולא בכיתה Log.
  2. יש לבטל את שאר שיטות מחזור החיים ב-MainActivity ולהוסיף Timber הצהרות יומן לכל אחת מהן. זהו הקוד:
override fun onResume() {
   super.onResume()
   Timber.i("onResume Called")
}

override fun onPause() {
   super.onPause()
   Timber.i("onPause Called")
}

override fun onStop() {
   super.onStop()
   Timber.i("onStop Called")
}

override fun onDestroy() {
   super.onDestroy()
   Timber.i("onDestroy Called")
}

override fun onRestart() {
   super.onRestart()
   Timber.i("onRestart Called")
}
  1. הידור והפעלה של DessertClicker שוב ובדיקת Logcat. הפעם יש לשים לב שבנוסף ל-onCreate() ול-onStart(), יש הודעת יומן לקריאה החוזרת של מחזור החיים של onResume().

כשפעילות מתחילה מאפס, אתם רואים את כל שלוש הקריאות הבאות למחזור חיים:

  • onCreate() כדי ליצור את האפליקציה.
  • onStart() כדי להפעיל אותו ולהציג אותו במסך.
  • onResume() כדי שפוקוס את הפעילות וכדי שהמשתמש יהיה מוכן לבצע בה פעולות.

למרות השם, השיטה של onResume() נקראת בעת ההפעלה, גם אם אין מה להמשיך.

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

תרחיש לדוגמה 1: פתיחה וסגירה של הפעילות

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

  1. הידור והפעלה של אפליקציית DessertClicker, אם היא עדיין לא פועלת. כפי שראיית, השיחות החוזרות (onCreate()), onStart() ו-onResume() נקראות כשהפעילות מתחילה בפעם הראשונה.
  2. מקישים כמה פעמים על הקאפקייקס.
  3. מקישים על לחצן 'הקודם' במכשיר. הודעה ביומן מאפשרת ל-onPause(), ל-onStop() ול-onDestroy() לקרוא בסדר הזה.

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

    ייתכן גם שהפעילות שלך תיסגר באופן מלא אם הקוד יופעל באופן ידני בשיטת finish() של הפעילות, או אם המשתמש יאלץ סגירה ידנית של האפליקציה. (לדוגמה, המשתמש יכול לאלץ סגירה של האפליקציה במסך האחרון בלחיצה על ה-X בפינה של החלון). ייתכן גם שמערכת Android תכבה את הפעילות שלה בעצמה, אם האפליקציה לא הוצגה במסך במשך זמן רב. הפעולה הזו מיועדת ל-Android כדי לאפשר שימוש באפליקציות של האפליקציה ובמשאבים שלה.
  4. אפשר להשתמש במסך האחרון כדי לחזור לאפליקציה. כאן מתבצע ה-Logcat:


    הפעילות הושמדת בשלב הקודם, כך שכשחוזרים לאפליקציה, Android מתחיל פעילות חדשה ומתקשר לשיטות onCreate(), onStart() ו-onResume(). לתשומת ליבך, הנתונים הסטטיסטיים של DessertClicker מהפעילות הקודמת לא נשמרו.

    נקודת המפתח הזו היא ש-onCreate() ו-onDestroy() מתקשרים רק פעם אחת בכל משך החיים של מופע פעילות אחד: onCreate() כדי להפעיל את האפליקציה בפעם הראשונה, ו-onDestroy() כדי לנקות את המשאבים שבהם האפליקציה משתמשת.

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

תרחיש לדוגמה 2: יציאה מהפעילות וחזרה אליה

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

הפעילות שלכם לא תיסגר במלואה בכל פעם שהמשתמש יצא מהפעילות:

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

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

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

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

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

  1. כאשר אפליקציית DessertClicker פועלת, לוחצים על קאפקייק מספר פעמים.
  2. לוחצים על הלחצן הראשי במכשיר וצופים ב-Logcat ב-Android Studio. כאשר חוזרים למסך הבית, האפליקציה מועברת אל הרקע במקום לסגור את האפליקציה לגמרי. חשוב לשים לב שהשיטה onPause() והשיטות onStop() נקראות יחד, אבל לא onDestroy().


    כשמתקשרים אל onPause(), האפליקציה לא מתמקדת יותר. אחרי onStop(), האפליקציה לא תוצג יותר במסך. למרות שהפעילות הופסקה, האובייקט Activity עדיין נמצא בזיכרון, ברקע. הפעילות לא נמחקה. המשתמש עשוי לחזור לאפליקציה, כך שמערכת Android תשמור את משאבי הפעילות שלך בסביבה.
  3. יש להשתמש במסך האחרון כדי לחזור לאפליקציה. יש לשים לב שב-Logcat מתבצעת הפעלה מחדש של הפעילות עם onRestart() ועם onStart(), ולאחר מכן להמשיך עם onResume().


    כשהפעילות חוזרת לחזית, השיטה onCreate() לא נקראת שוב. אובייקט הפעילות לא שנהרס, כך שאין צורך ליצור אותו שוב. במקום onCreate(), מתבצעת קריאה לשיטה onRestart(). הערה: הפעם כאשר הפעילות חוזרת לחזית, המספר נמכר בקינוחים נשמר.
  4. צריך להפעיל אפליקציה אחת לפחות שאינה DessertClicker כדי שבמכשיר יהיו כמה אפליקציות במסך האחרון.
  5. מעלים את המסך 'אחרונים' ופותחים פעילות חדשה. לאחר מכן חוזרים לאפליקציות האחרונות ומחזירים את DessertClicker לחזית.

    לתשומת ליבך, כאן מוצגות אותן הקריאות החוזרות ב-Logcats כמו כשלוחצים על הלחצן Home. קריאה לפעולה של onPause() ושל onStop() מתבצעת כשהאפליקציה עוברת לרקע, ולאחר מכן onRestart(), onStart() ו-onResume() כשהיא מופעלת.

    הנקודה החשובה כאן היא שonStart() ו-onStop() יקראו כמה פעמים כשהמשתמש ינווט אל הפעילות וממנו. עליך לעקוף את השיטות האלה כדי להפסיק את פעולת האפליקציה כשהיא עוברת לרקע, או להפעיל אותה שוב כשהיא תחזור לחזית.

    מה לגבי onRestart()? השיטה של onRestart() דומה מאוד ל-onCreate(). הקריאה אל onCreate() או onRestart() מוצגת לפני שהפעילות הופכת לגלויה. השיטה onCreate() נקראת רק בפעם הראשונה, ואחר כך onRestart() מתקשרים. השיטה onRestart() היא מקום להוספת קוד שאליו רוצים להתקשר רק אם הפעילות לא מתחילה בפעם הראשונה.

תרחיש לדוגמה 3: הסתרה חלקית של הפעילות

למדת שכשאפליקציה מופעלת והאפליקציה onStart() מופעלת, האפליקציה הופכת לגלויה במסך. כשהאפליקציה מופעלת מחדש וקוראים ל-onResume(), המשתמש מקבל פוקוס של המשתמש. החלק במחזור החיים שבו האפליקציה מוצגת במסך מלא, ומתמקד במשתמש, נקרא מחזור החיים האינטראקטיבי.

כשהאפליקציה פועלת ברקע, המיקוד יאבד אחרי onPause(), והאפליקציה לא תוצג יותר אחרי onStop().

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

  1. כשאפליקציית DessertClicker פועלת, לוחצים על הלחצן שיתוף בפינה השמאלית העליונה של המסך.




    פעילות השיתוף מופיעה בחצי התחתון של המסך, אבל הפעילות עדיין גלויה בחצי העליון.
  2. כדאי לבדוק את Logcat כדי לראות רק להתקשר אל onPause().


    במקרה הזה, onStop() לא נקרא כי הפעילות עדיין גלויה. אבל הפעילות לא מתמקדת למשתמש, והוא לא יכול לבצע בה פעולות. המיקוד "share" של פעילות בחזית הוא משתמש.

    למה ההבדל הזה חשוב? כדאי לקחת בחשבון את אפליקציית הפיזיקה. ייתכן שתרצו שהסימולציה תיפסק כאשר האפליקציה פועלת ברקע ותמשיך לפעול כאשר האפליקציה מוסתרת באופן חלקי. במקרה כזה, הסימולציה תיפסק ב-onStop(). אם ברצונך שהסימולציה תיפסק כאשר הפעילות מוסתרת באופן חלקי, יש להזין את הקוד כדי להפסיק את הסימולציה ב-onPause().

    כל קוד שפועל ב-onPause() חוסם את ההצגה של פריטים אחרים, לכן יש לוודא שהקוד לא יהיה קל ב-onPause(). לדוגמה, אם שיחת טלפון נכנסת, הקוד בonPause() עשוי לעכב את ההתראה על השיחה הנכנסת.
  3. לוחצים מחוץ לתיבת הדו-שיח של השיתוף כדי לחזור לאפליקציה, ושימו לב שהשם onResume() נקרא.

    גם onResume() וגם onPause()הנושאים צריכים להתמקד. השיטה onResume() נקראת כשהפעילות ממקדת ו-onPause() נקראת כאשר הפעילות מאבדת את המיקוד.

מחזור החיים של מקטע Android דומה למחזור החיים, וכן למספר שיטות ספציפיות למקטעים.

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

כל מסך באפליקציית AndroidTrivia הוא Fragment.

כדי שהדברים יהיו פשוטים, אתם צריכים להשתמש ב-Android Log API במשימה הזו, ולא בספריית Timber.

  1. פותחים את אפליקציית AndroidTrivia מקוד הקוד האחרון, או מורידים את קוד הפתרון AndroidTrivia מ-GitHub.
  2. פותחים את הקובץ TitleFragment.kt. שימו לב: ייתכן שמערכת Android Studio תציג שגיאות מחייבות ושגיאות של קובצי עזר שלא נפתרו עד לבנות את האפליקציה מחדש.
  3. יש לגלול למטה אל השיטה onCreateView(). שימו לב שבמקום הזה, הפריסה של קטע הקוד מנופחת ומתרחשים איגודי נתונים.
  4. יש להוסיף הצהרת רישום בשיטה onCreateView(), בין השורה ל-setHasOptionsMenu() לשיחה האחרונה כדי לחזור:
setHasOptionsMenu(true)

Log.i("TitleFragment", "onCreateView called")

return binding.root
  1. מתחת לשיטה onCreateView(), מוסיפים הצהרות רישום ביומן לכל אחת מהשיטות שנותרו במחזור החיים של מקטע. הנה הקוד:
override fun onAttach(context: Context?) {
   super.onAttach(context)
   Log.i("TitleFragment", "onAttach called")
}
override fun onCreate(savedInstanceState: Bundle?) {
   super.onCreate(savedInstanceState)
   Log.i("TitleFragment", "onCreate called")
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
   super.onActivityCreated(savedInstanceState)
   Log.i("TitleFragment", "onActivityCreated called")
}
override fun onStart() {
   super.onStart()
   Log.i("TitleFragment", "onStart called")
}
override fun onResume() {
   super.onResume()
   Log.i("TitleFragment", "onResume called")
}
override fun onPause() {
   super.onPause()
   Log.i("TitleFragment", "onPause called")
}
override fun onStop() {
   super.onStop()
   Log.i("TitleFragment", "onStop called")
}
override fun onDestroyView() {
   super.onDestroyView()
   Log.i("TitleFragment", "onDestroyView called")
}
override fun onDetach() {
   super.onDetach()
   Log.i("TitleFragment", "onDetach called")
}
  1. הידור והפעלה של האפליקציה ופתיחת Logcat.
  2. מקלידים I/TitleFragment בשדה החיפוש כדי לסנן את היומן. כשהאפליקציה תתחיל, ה-Logcat ייראה בערך בצילום המסך הבא:

כאן תוכלו לראות את כל מחזור החיים של קטע הקוד, כולל התכונות הבאות (callbacks):

  • onAttach(): קריאה במקרה שקטע הקוד משויך לפעילות הבעלים שלו.
  • onCreate(): בדומה ל-onCreate() עבור הפעילות, הפונקציה onCreate() עבור קטע הקוד נקראת לבצע יצירת מקטע ראשוני (מלבד פריסה).
  • onCreateView(): נשלחה בקשה להגדיל את פריסת המקטע.
  • onActivityCreated(): התקשרות כשהפעילות של הבעלים של onCreate() הושלמה. לא תהיה לך גישה לפעילות שלך עד שתהיה קריאה לשיטה הזו.
  • onStart(): מופעל כשקטע הקוד גלוי, במקביל לפעילות onStart().
  • onResume(): מתבצעת קריאה כאשר המקטע מקבל את מיקוד המשתמש; מקביל לפעולה onResume().
  1. יש להקיש על הלחצן הפעלה כדי להמשיך למשחק הטריוויה, ולראות עכשיו את יומן הרישום.

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

  • onPause(): מתבצעת כשהקטע מאבד את מיקוד המשתמש, המקביל לפעילות onPause().
  • onStop(): מתבצעת קריאה כשקטע הקוד לא גלוי יותר במסך; מקביל לפעולה onStop()'
  • onDestroyView(): קריאה לפעולה כאשר אין יותר צורך בתצוגת קטע הקוד, כדי לנקות את המשאבים המשויכים לתצוגה המפורטת הזו.
  1. באפליקציה, מקישים על הלחצן 'למעלה' (החץ שבפינה הימנית העליונה של המסך) כדי לחזור למקטע הכותרת.


    ייתכן שהפעם, onAttach() ו-onCreate() לא יוקראו כדי להפעיל את המקטע. אובייקט המקטע עדיין קיים והוא עדיין מחובר לפעילות הבעלים שלו, כך שמחזור החיים יתחיל שוב עם onCreateView().
  2. לוחצים על הלחצן הראשי במכשיר. שימו לב ב-Logcat שרק קריאה ל-onPause() ול-onStop() נקראת. התנהגות זו זהה לזו של הפעילות: החזרה הביתה מעבירה את הפעילות וקטע הקוד אל הרקע.
  3. משתמשים במסך האחרון כדי לחזור לאפליקציה. בדיוק כמו במקרה של הפעילות, השיטות onStart() ו-onResume() נקראות כדי להחזיר את הקטע לחזית.

פרויקט ב-Android Studio: DessertClickerLogs

מחזור חיים של פעילות

  • מחזור החיים של הפעילות הוא קבוצת מצבים שבעזרתם פעילות מועברת. מחזור החיים של הפעילות מתחיל עם יצירת הפעילות הראשונה, ומסתיים בעת השמדת הפעילות.
  • כשהמשתמש מנווט בין פעילויות בתוך האפליקציה ומחוצה לה, כל פעילות עוברת בין מצבים במחזור החיים של הפעילות.
  • לכל מדינה במחזור החיים יש שיטת קריאה חוזרת (callback) תואמת שניתן לבטל בכיתה Activity. יש שבע שיטות במחזור חיים:
    onCreate()
    onStart()
    onPause()
    onRestart()
    onResume()
    onStop()
    onDestroy()
  • כדי להוסיף התנהגות שמתרחשת כשהפעילות עוברת למצב מחזור חיים, יש לעקוף את שיטת השיחה החוזרת של המדינה.
  • כדי להוסיף שיטות לשינוי שלד לכיתות שלכם ב-Android Studio, בוחרים באפשרות קוד > שיטות לעקיפת הכלל או מקישים על Control+o.

התחברות באמצעות יומן רישום

  • ה-API לרישום Android, ובמיוחד הכיתה Log, מאפשרים לך לכתוב הודעות קצרות המוצגות ביומןאט ב-Android Studio.
  • שימוש ב-Log.i() כדי לכתוב הודעת מידע. לשיטה הזו יש שני ארגומנטים: היומן תג, בדרך כלל שם הכיתה וההודעה ביומן, מחרוזת קצרה.
  • בחלונית Logcat ב-Android Studio אפשר להציג את יומני המערכת, כולל ההודעות שאתם כותבים.

התחברות באמצעות עץ

Timber היא ספריית יומנים עם כמה יתרונות בהשוואה ל-Android Log API. ובפרט, הספרייה Timber:

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

כדי להשתמש ב-Timber, יש להוסיף את התלות שלו בקובץ Gradle ולהרחיב את הכיתה Application כדי להפעיל אותו:

  • Application הוא סיווג בסיס המכיל מצב אפליקציה גלובלי עבור כל האפליקציה שלך. יש סיווג Application המוגדר כברירת מחדל ב-Android. אם לא מציינים אותו, יש סיווג ברירת מחדל ל-Android. אפשר ליצור מחלקת משנה אחת (Application) כדי להפעיל ספריות ברמת האפליקציה, כמו Timber.
  • ניתן להוסיף את הכיתה Application המותאמת אישית לאפליקציה על ידי הוספת המאפיין android:name לאלמנט <application> במניפסט Android. אל תשכחו לעשות זאת!
  • יש להשתמש ב-Timber.i() כדי לכתוב הודעות יומן באמצעות Timber. לשיטה הזו יש רק ארגומנט אחד: ההודעה לכתיבה. תג היומן (שם הכיתה) יתווסף עבורכם באופן אוטומטי.

קורס אוניברסיטה:

התיעוד של מפתח Android:

אחר:

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

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

המורים יכולים להשתמש בהצעות האלה כמה שפחות, ומומלץ להקצות להן כל שיעורי בית שדעתם מתאימה להם.

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

שינוי אפליקציה

פותחים את אפליקציית DiceRoller משיעור 1. (הורידו את אפליקציית DiceRoller כאן אם אין לכם את האפליקציה). מוסיפים את התמיכה של Timb לאפליקציה הזו ומשלימים את אותו תהליך שבו השתמשתם באפליקציה DessertClicker. יש לבטל את כל הקריאה החוזרת על מחזור החיים ולהוסיף הודעות רישום ביומן לכל קריאה חוזרת (callback).

מענה על השאלות הבאות

שאלה 1

איזה מהמצבים הבאים אינו מצב מחזור חיים של פעילות?

  • התחיל
  • ממתין
  • תאריך יצירה
  • הושמד

שאלה 2

איזו שיטה במחזור החיים נקראת כדי שהפעילויות יהיו גלויות?

  • onPause()
  • onVisible()
  • onStart()
  • onDestroy()

שאלה 3

איזו שיטה במחזור החיים נקראת כדי להתמקד?

  • onResume()
  • onVisible()
  • onStart()
  • onFocus()

שאלה 4

מתי onCreate() מתקשרת בפעילות?

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

שליחת האפליקציה לבדיקה

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

  • תלות ב-Timber בקובץ build.gradle של האפליקציה.
  • תת-קבוצה מותאמת אישית של Application שמאתחלת את Timber ב-onCreate().
  • מאפיין עבור אותה קבוצת משנה מותאמת אישית במניפסט Android.
  • שינויים של שיטות ב-MainActivity עבור כל השיטות של קריאה חוזרת (callback) במחזור החיים, עם שיחות אל Timber.i() לצורך רישום ביומן.

לשיעור הבא: 4.2: מצבים מורכבים של מחזור חיים

קישורים למעבדות אחרות של הקוד בקורס הזה זמינים בדף הנחיתה של Android Kotlin Fundamentals Codelabs.