Android Kotlin Fundamentals 06.3: שימוש ב-LiveData כדי לשלוט במצבי לחצנים

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

מבוא

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

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

דברים שחשוב לדעת

כדאי שתכירו את:

  • בניית ממשק משתמש בסיסי (UI) באמצעות פעילות, שברים וצפיות.
  • מעבר בין מקטעים ושימוש ב-safeArgs כדי להעביר נתונים בין מקטעים.
  • הצגה של מודלים, הצגה של מפעלי מודלים, טרנספורמציות וLiveData ושל הבודקים שלהם.
  • איך ליצור מסד נתונים מסוג Room, ליצור אובייקט גישה לנתונים (DAO) ולהגדיר ישויות.
  • איך להשתמש בשגרות באינטראקציות במסד נתונים ובמשימות ארוכות אחרות.

מה תלמדו

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

הפעולות שתבצעו:

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

ב-Codelab הזה, תיצרו הקלטה באיכות השינה וממשק המשתמש הסופי של אפליקציית MyMySleepquality.

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

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

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

התהליך של המשתמש הוא:

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

האפליקציה הזו משתמשת בארכיטקטורה פשוטה, כפי שמפורט בהמשך בהקשר של הארכיטקטורה המלאה. האפליקציה משתמשת רק ברכיבים הבאים:

  • בקר ממשק משתמש
  • הצגת הדגם ו-LiveData
  • מסד נתונים של חדר

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

שלב 1: בודקים את הקוד

  1. כדי להתחיל, צריך להמשיך להזין את הקוד בסיום סוף שיעור ה-Lab האחרון או להוריד את הקוד למתחילים.
  2. בקוד למתחילים, בודקים את SleepQualityFragment. כיתה זו מנפחת את הפריסה, מקבלת את האפליקציה ומחזירה את binding.root.
  3. פותחים את Navigation.xml בעורך העיצוב. רואים שיש מסלול ניווט מSleepTrackerFragment אל SleepQualityFragment, ואז חזרה מSleepQualityFragment לSleepTrackerFragment.



  4. יש לבדוק את הקוד של Navigation.xml. באופן ספציפי, יש לחפש את <argument> בשם sleepNightKey.

    כשהמשתמש עובר מ-SleepTrackerFragment אל SleepQualityFragment,, האפליקציה תעביר sleepNightKey אל SleepQualityFragment למשך הלילה שיש לעדכן.

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

תרשים הניווט כבר כולל את הנתיבים מ-SleepTrackerFragment אל SleepQualityFragment וחזרה. עם זאת, ה-handlers של הקליקים שמטמיעים את הניווט מקטע אחד לקטע הבא לא עוברים עדיין קוד. את הקוד הזה מוסיפים עכשיו בViewModel.

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

  1. פתיחת SleepTrackerViewModel צריך להוסיף ניווט כך שכאשר המשתמש מקיש על הלחצן עצירה, האפליקציה מנווטת אל SleepQualityFragment כדי לאסוף דירוג איכות.
  2. בSleepTrackerViewModel, יוצרים LiveData שמשתנה כשהאפליקציה צריכה לנווט אל SleepQualityFragment. מומלץ להשתמש באותיות רישיות כדי לחשוף רק גרסה של LiveData שניתן להוריד מ-ViewModel.

    אפשר למקם את הקוד הזה בכל מקום ברמה העליונה של גוף הכיתות.
private val _navigateToSleepQuality = MutableLiveData<SleepNight>()

val navigateToSleepQuality: LiveData<SleepNight>
   get() = _navigateToSleepQuality
  1. צריך להוסיף פונקציה doneNavigating() שמאפסת את המשתנה שמפעיל את הניווט.
fun doneNavigating() {
   _navigateToSleepQuality.value = null
}
  1. ב-handler של הלחצן Stop, לוחצים על onStopTracking() כדי להפעיל את הניווט אל SleepQualityFragment. מגדירים את המשתנה _navigateToSleepQuality בסוף הפונקציה כדבר האחרון בבלוק launch{}. חשוב לשים לב שהמשתנה הזה מוגדר כ-night. כשהמשתנה מקבל ערך, האפליקציה תנווט אל SleepQualityFragment לאורך הלילה.
_navigateToSleepQuality.value = oldNight
  1. ה-SleepTrackerFragment צריך לשמור על _navigateToSleepQuality כדי שהאפליקציה תוכל לדעת מתי לנווט. ב-SleepTrackerFragment, ב-onCreateView(), מוסיפים צופה עבור navigateToSleepQuality(). לתשומת ליבכם: הייבוא של הערך הזה אינו ברור, ואתם צריכים לייבא את androidx.lifecycle.Observer.
sleepTrackerViewModel.navigateToSleepQuality.observe(this, Observer {
})

  1. בתוך החסימה של הצופה, מנווטים ועוברים עם המזהה של הלילה הנוכחי, ומתקשרים אל doneNavigating(). אם הייבוא לא ברור, מייבאים את androidx.navigation.fragment.findNavController.
night ->
night?.let {
   this.findNavController().navigate(
           SleepTrackerFragmentDirections
                   .actionSleepTrackerFragmentToSleepQualityFragment(night.nightId))
   sleepTrackerViewModel.doneNavigating()
}
  1. בונים ומפעילים את האפליקציה. מקישים על התחלה, ולאחר מכן מקישים על עצירה כדי לעבור למסך SleepQualityFragment. כדי לחזור, יש להשתמש בלחצן 'הקודם' של המערכת.

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

שלב 1: יצירת מודל מודל ו-ViewModel תצורה

  1. בחבילה של sleepquality, יוצרים או פותחים את SleepqualityViewModel.kt.
  2. יצירה של כיתה SleepQualityViewModel שיש בה sleepNightKey ומסד נתונים כארגומנטים. בדיוק כמו ב-SleepTrackerViewModel, עליך לעבור ב-database מהמפעל. כמו כן, עליך לעבור ב-sleepNightKey מהניווט.
class SleepQualityViewModel(
       private val sleepNightKey: Long = 0L,
       val database: SleepDatabaseDao) : ViewModel() {
}
  1. בתוך הכיתה SleepQualityViewModel, יש להגדיר Job וuiScope, ולעקוף את onCleared().
private val viewModelJob = Job()
private val uiScope = CoroutineScope(Dispatchers.Main + viewModelJob)

override fun onCleared() {
   super.onCleared()
   viewModelJob.cancel()
}
  1. כדי לחזור אל SleepTrackerFragment עם אותו דפוס המופיע למעלה, יש להצהיר על _navigateToSleepTracker. הטמעה של navigateToSleepTracker ושל doneNavigating().
private val _navigateToSleepTracker = MutableLiveData<Boolean?>()

val navigateToSleepTracker: LiveData<Boolean?>
   get() = _navigateToSleepTracker

fun doneNavigating() {
   _navigateToSleepTracker.value = null
}
  1. אפשר ליצור handler אחד של קליק, onSetSleepQuality(), כדי להשתמש בכל התמונות באיכות שינה.

    יש להשתמש באותו דפוס קורטיון כמו בדוגמת הקוד הקודמת:
  • פותחים שגרת המשך ב-uiScope ועוברים לסדרן I/O.
  • אפשר לקבל את tonight באמצעות הsleepNightKey.
  • מגדירים את איכות השינה.
  • מעדכנים את מסד הנתונים.
  • הפעלת הניווט.

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

fun onSetSleepQuality(quality: Int) {
        uiScope.launch {
            // IO is a thread pool for running operations that access the disk, such as
            // our Room database.
            withContext(Dispatchers.IO) {
                val tonight = database.get(sleepNightKey) ?: return@withContext
                tonight.sleepQuality = quality
                database.update(tonight)
            }

            // Setting this state variable to true will alert the observer and trigger navigation.
            _navigateToSleepTracker.value = true
        }
    }
  1. בחבילה sleepquality, יש ליצור או לפתוח את SleepQualityViewModelFactory.kt ולהוסיף את הכיתה SleepQualityViewModelFactory, כפי שמוצג למטה. לכיתה הזו יש גרסה זהה של אותו קוד אימות שמופיע קודם לכן. יש לבדוק את הקוד לפני שממשיכים.
class SleepQualityViewModelFactory(
       private val sleepNightKey: Long,
       private val dataSource: SleepDatabaseDao) : ViewModelProvider.Factory {
   @Suppress("unchecked_cast")
   override fun <T : ViewModel?> create(modelClass: Class<T>): T {
       if (modelClass.isAssignableFrom(SleepQualityViewModel::class.java)) {
           return SleepQualityViewModel(sleepNightKey, dataSource) as T
       }
       throw IllegalArgumentException("Unknown ViewModel class")
   }
}

שלב 2: עדכון ה-SleepqualityFragment

  1. פתיחת SleepQualityFragment.kt
  2. בonCreateView(), אחרי קבלת application, עליך לקבל את ה-arguments שהגיע עם הניווט. הארגומנטים האלה נמצאים ב-SleepQualityFragmentArgs. יש לחלץ אותם מהחבילה.
val arguments = SleepQualityFragmentArgs.fromBundle(arguments!!)
  1. עכשיו אפשר לקבל את dataSource.
val dataSource = SleepDatabase.getInstance(application).sleepDatabaseDao
  1. יוצרים מפעל ועוברים את dataSource ואת sleepNightKey.
val viewModelFactory = SleepQualityViewModelFactory(arguments.sleepNightKey, dataSource)
  1. קבלת קובץ עזר של ViewModel.
val sleepQualityViewModel =
       ViewModelProviders.of(
               this, viewModelFactory).get(SleepQualityViewModel::class.java)
  1. צריך להוסיף את ViewModel לאובייקט המחייב. (אם מופיעה שגיאה עם האובייקט המחייב, התעלמו ממנה בשלב זה).
binding.sleepQualityViewModel = sleepQualityViewModel
  1. מוסיפים את הצופה. כשתופיע בקשה, מייבאים את androidx.lifecycle.Observer.
sleepQualityViewModel.navigateToSleepTracker.observe(this, Observer {
   if (it == true) { // Observed state is true.
       this.findNavController().navigate(
               SleepQualityFragmentDirections.actionSleepQualityFragmentToSleepTrackerFragment())
       sleepQualityViewModel.doneNavigating()
   }
})

שלב 3: מעדכנים את קובץ הפריסה ומפעילים את האפליקציה

  1. פותחים את קובץ הפריסה fragment_sleep_quality.xml. בבלוק <data>, מוסיפים משתנה ל-SleepQualityViewModel.
 <data>
       <variable
           name="sleepQualityViewModel"
           type="com.example.android.trackmysleepquality.sleepquality.SleepQualityViewModel" />
   </data>
  1. עבור כל אחת משש התמונות באיכות שינה, יש להוסיף handler של קליק כמו זה שלמטה. להתאים את דירוג האיכות לתמונה.
android:onClick="@{() -> sleepQualityViewModel.onSetSleepQuality(5)}"
  1. מנקים ובונים מחדש את הפרויקט. הפעולה הזו אמורה לתקן שגיאות עם האובייקט המחייב. אחרת, מנקים את המטמון (קובץ > ביטול מטמון / הפעלה מחדש) ובונים מחדש את האפליקציה.

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

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

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

שלב 1: עדכון מצבי לחצנים

הרעיון הוא להגדיר את מצב הלחצן כך בהתחלה, רק הלחצן התחלה, כלומר יהיה ניתן ללחוץ עליו.

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

  1. פותחים את קובץ הפריסה fragment_sleep_tracker.xml.
  2. יש להוסיף את המאפיין android:enabled לכל לחצן. הנכס android:enabled הוא ערך בוליאני שמציין אם הלחצן מופעל או לא. (ניתן להקיש על לחצן מופעל; לחצן מושבת יכול') לתת לנכס את הערך של משתנה מדינה, שאותו תגדירו בעוד רגע.

start_button:

android:enabled="@{sleepTrackerViewModel.startButtonVisible}"


:stop_button

android:enabled="@{sleepTrackerViewModel.stopButtonVisible}"

clear_button:

android:enabled="@{sleepTrackerViewModel.clearButtonVisible}"
  1. פותחים את SleepTrackerViewModel ויוצרים שלושה משתנים תואמים. יש להקצות כל משתנה טרנספורמציה שבודקת אותו.
  • יש להפעיל את הלחצן התחלה כאשר tonight הוא null.
  • יש להפעיל את הלחצן עצירה כאשר tonight אינו null.
  • יש להפעיל את הלחצן ניקוי רק אם nights, ולכן מסד הנתונים מכיל לילות שינה.
val startButtonVisible = Transformations.map(tonight) {
   it == null
}
val stopButtonVisible = Transformations.map(tonight) {
   it != null
}
val clearButtonVisible = Transformations.map(nights) {
   it?.isNotEmpty()
}
  1. מריצים את האפליקציה ועורכים ניסויים בלחצנים.

שלב 2: משתמשים במזנון כדי להודיע למשתמש

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

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

  1. בSleepTrackerViewModel, יוצרים את האירוע מסוג מקיף.
private var _showSnackbarEvent = MutableLiveData<Boolean>()

val showSnackBarEvent: LiveData<Boolean>
   get() = _showSnackbarEvent
  1. לאחר מכן מטמיעים את doneShowingSnackbar().
fun doneShowingSnackbar() {
   _showSnackbarEvent.value = false
}
  1. ב-SleepTrackerFragment, ב-onCreateView(), מוסיפים צופה:
sleepTrackerViewModel.showSnackBarEvent.observe(this, Observer { })
  1. בתוך בלוק הצופה, מציגים את מזנון ומאפסים את האירוע באופן מיידי.
   if (it == true) { // Observed state is true.
       Snackbar.make(
               activity!!.findViewById(android.R.id.content),
               getString(R.string.cleared_message),
               Snackbar.LENGTH_SHORT // How long to display the message.
       ).show()
       sleepTrackerViewModel.doneShowingSnackbar()
   }
  1. ב-SleepTrackerViewModel, מפעילים את האירוע בשיטת onClear(). כדי לעשות זאת, צריך להגדיר את ערך האירוע כ-true בתוך הבלוק launch:
_showSnackbarEvent.value = true
  1. אפשר לפתח ולהפעיל את האפליקציה!

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

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

  • יש ליצור ViewModel וViewModelFactory ולהגדיר מקור נתונים.
  • הפעלת הניווט. כדי להפריד בין חששות, יש למקם את הגורם המטפל בקליקים במודל התצוגה ואת הניווט בשבר.
  • כדי לעקוב אחר שינויים במדינה ולהגיב אליה, יש להשתמש באותיות רישיות עם LiveData.
  • שימוש בטרנספורמציות עם LiveData.
  • יוצרים מסד נתונים של Singleton.
  • הגדרת שגרים לפעולות מסדי נתונים.

ניווט מופעל

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

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

הגדרת המאפיין android:Enabled

  • המאפיין android:enabled מוגדר ב-TextView בירושה על ידי כל כיתות המשנה, כולל Button.
  • המאפיין android:enabled קובע אם הערך View יופעל. המשמעות של "Enabled" משתנה לפי סיווג משנה. לדוגמה, אם המדיניות EditText לא מופעלת, המשתמש לא יכול לערוך את הטקסט שכלול בה, ופרמטר Button שלא מופעל מונע מהמשתמש להקיש על הלחצן.
  • המאפיין enabled אינו זהה למאפיין visibility.
  • ניתן להשתמש במפות טרנספורמציה כדי להגדיר את הערך של המאפיין enabled של לחצנים בהתאם למצב של אובייקט או משתנה אחר.

נקודות נוספות שחלות על Lab Lab זה:

  • כדי להפעיל את ההתראות למשתמשים, אפשר להשתמש באותה שיטה שבה משתמשים כדי להפעיל את הניווט.
  • אפשר להשתמש בSnackbar כדי להודיע למשתמש.

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

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

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

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

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

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

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

שאלה 1

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

מהם השלבים לשימוש בערך LiveData, שנקרא gotoBlueFragment, כדי להפעיל ניווט מהמקטע האדום למקטע הכחול? יש לבחור בכל האפשרויות המתאימות:

  • בViewModel, מגדירים את הערך LiveData gotoBlueFragment.
  • בRedFragment, יש לשים לב לערך gotoBlueFragment. יש ליישם את הקוד observe{} כדי לנווט אל BlueFragment במקרה הצורך, ולאחר מכן לאפס את הערך של gotoBlueFragment כדי לציין שהניווט הושלם.
  • יש לוודא שהקוד מגדיר את המשתנה gotoBlueFragment לערך שמפעיל את הניווט בכל פעם שהאפליקציה צריכה לעבור מ-RedFragment ל-BlueFragment.
  • יש לוודא שהקוד מגדיר handler של onClick עבור View שעליו המשתמש לוחץ כדי לנווט אל BlueFragment, כאשר ה-handler של onClick בודק את הערך goToBlueFragment.

שאלה 2

ניתן לקבוע אם Button יופעל (ניתן ללחוץ עליו) או לא באמצעות LiveData. איך אפשר לוודא שהאפליקציה תשנה את הלחצן UpdateNumber כך:

  • הלחצן מופעל אם לערך myNumber יש ערך גדול מ-5.
  • הלחצן לא מופעל אם myNumber שווה ל-5 או קטן ממנו.

נניח שהפריסה שמכילה את הלחצן UpdateNumber כוללת את המשתנה <data> של NumbersViewModel, כפי שמוצג כאן:

<data>
   <variable
       name="NumbersViewModel"
       type="com.example.android.numbersapp.NumbersViewModel" />
</data>

נניח שמזהה הלחצן בקובץ הפריסה הוא:

android:id="@+id/update_number_button"

מה עוד צריך לעשות? יש לבחור בכל האפשרויות הרלוונטיות.

  • בכיתה NumbersViewModel, מגדירים משתנה LiveData, myNumber, שמייצג את המספר. צריך גם להגדיר משתנה שהערך שלו מוגדר על ידי קריאה ל-Transform.map() במשתנה myNumber, שמחזירה בוליאני שמציין אם המספר גדול מ-5.

    באופן ספציפי, בViewModel, יש להוסיף את הקוד הבא:
val myNumber: LiveData<Int>

val enableUpdateNumberButton = Transformations.map(myNumber) {
   myNumber > 5
}
  • בפריסת ה-XML, יש להגדיר את המאפיין android:enabled של update_number_button button כ-NumberViewModel.enableUpdateNumbersButton.
android:enabled="@{NumbersViewModel.enableUpdateNumberButton}"
  • ב-Fragment שמשתמש במחלקה NumbersViewModel, מוסיפים צופה למאפיין enabled של הלחצן.

    באופן ספציפי, בFragment, יש להוסיף את הקוד הבא:
// Observer for the enabled attribute
viewModel.enabled.observe(this, Observer<Boolean> { isEnabled ->
   myNumber > 5
})
  • בקובץ הפריסה, יש להגדיר את המאפיין android:enabled של update_number_button button ל-"Observable".

לשיעור הבא: יסודות של 7.1 RecyclerView

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