ה-codelab הזה הוא חלק מהקורס Android Kotlin Fundamentals. כדי להפיק את המרב מהקורס הזה, מומלץ לעבוד על ה-codelabs לפי הסדר. כל ה-codelab של הקורס מפורטים בדף הנחיתה של ה-codelab בנושא יסודות Kotlin ל-Android.
מבוא
בשיעור הזה נסביר איך להשתמש ב-ViewModel
ובקטעים ביחד כדי להטמיע ניווט. חשוב לזכור שהמטרה היא להעביר את הלוגיקה של מתי לנווט אל ViewModel
, אבל להגדיר את הנתיבים בקטעים ובקובץ הניווט. כדי להשיג את המטרה הזו, משתמשים במודלים של תצוגות, בקטעי קוד, ב-LiveData
ובאובייקטים מסוג Observer.
בסיום ה-codelab מוצגת דרך חכמה לעקוב אחרי מצבי הלחצנים עם מינימום קוד, כך שכל לחצן מופעל וניתן ללחיצה רק כשיש היגיון בכך שהמשתמש יקיש על הלחצן הזה.
מה שכדאי לדעת
חשוב שתכירו את:
- בניית ממשק משתמש (UI) בסיסי באמצעות פעילות, רכיבים ותצוגות.
- ניווט בין פרגמנטים ושימוש ב-
safeArgs
כדי להעביר נתונים בין פרגמנטים. - אפשר לראות את המודלים, את מפעלי המודלים, את הטרנספורמציות ואת
LiveData
ואת האובזרברים שלהם. - איך יוצרים מסד נתונים
Room
, יוצרים אובייקט גישה לנתונים (DAO) ומגדירים ישויות. - איך משתמשים ב-coroutines לאינטראקציות עם מסדי נתונים ולמשימות אחרות שפועלות לאורך זמן.
מה תלמדו
- איך מעדכנים רשומה קיימת של איכות השינה במסד הנתונים.
- איך משתמשים ב-
LiveData
כדי לעקוב אחרי מצבי לחצנים. - איך להציג סנקבר בתגובה לאירוע.
הפעולות שתבצעו:
- הרחבת האפליקציה TrackMySleepQuality כדי לאסוף דירוג איכות, להוסיף את הדירוג למסד הנתונים ולהציג את התוצאה.
- משתמשים ב-
LiveData
כדי להפעיל את התצוגה של חטיף. - משתמשים ב-
LiveData
כדי להפעיל ולהשבית את הלחצנים.
בשיעור הזה תבנו את ההקלטה של איכות השינה ואת ממשק המשתמש הסופי של האפליקציה TrackMySleepQuality.
לאפליקציה יש שני מסכים שמיוצגים על ידי קטעים, כמו שמוצג באיור שלמטה.
במסך הראשון, שמוצג בצד ימין, יש לחצנים להתחלת המעקב ולהפסקתו. במסך מוצגים כל נתוני השינה של המשתמש. הלחצן ניקוי מוחק באופן סופי את כל הנתונים שהאפליקציה אספה על המשתמש.
במסך השני, שמוצג בצד שמאל, בוחרים את דירוג איכות השינה. באפליקציה, הדירוג מיוצג בצורה מספרית. למטרות פיתוח, האפליקציה מציגה גם את סמלי הפנים וגם את הערכים המספריים שלהם.
מסלול המשתמש הוא כדלקמן:
- המשתמש פותח את האפליקציה ומוצג לו מסך מעקב השינה.
- המשתמש מקיש על הלחצן התחלה. השדה הזה מתעד את שעת ההתחלה ומציג אותה. הלחצן התחלה מושבת, והלחצן עצירה מופעל.
- המשתמש מקיש על הלחצן הפסקה. השעה שבה תסיימו לישון תתועד ותיפתח לכם האפשרות לדרג את איכות השינה.
- המשתמש בוחר בסמל של איכות השינה. המסך נסגר, ובמסך המעקב מוצגים שעת סיום השינה ואיכות השינה. הלחצן עצירה מושבת והלחצן התחלה מופעל. האפליקציה מוכנה לעוד לילה.
- הלחצן ניקוי מופעל בכל פעם שיש נתונים במסד הנתונים. כשמשתמש מקיש על הלחצן ניקוי, כל הנתונים שלו נמחקים בלי אפשרות לשחזור – לא מוצגת הודעה עם השאלה 'האם אתה בטוח?'.
האפליקציה הזו משתמשת בארכיטקטורה פשוטה, כפי שמוצג בהמשך בהקשר של הארכיטקטורה המלאה. האפליקציה משתמשת רק ברכיבים הבאים:
- בקר ממשק משתמש
- הצגת הדגם ו-
LiveData
- מסד נתונים של Room
בשיעור הזה אנחנו מניחים שאתם יודעים איך להטמיע ניווט באמצעות קטעים ואת קובץ הניווט. כדי שתוכלו לשמור את העבודה שלכם, סיפקנו חלק גדול מהקוד הזה.
שלב 1: בדיקת הקוד
- כדי להתחיל, אפשר להמשיך עם הקוד שלכם מסוף ה-codelab הקודם, או להוריד את הקוד לתחילת הדרך.
- בקוד המתחיל, בודקים את
SleepQualityFragment
. המחלקות האלה מרחיבות את הפריסה, מקבלות את האפליקציה ומחזירות אתbinding.root
. - פותחים את navigation.xml בכלי לעריכת עיצוב. אפשר לראות שיש נתיב ניווט מ
SleepTrackerFragment
אלSleepQualityFragment
, וחזרה מSleepQualityFragment
אלSleepTrackerFragment
. - בודקים את הקוד של navigation.xml. בפרט, מחפשים את
<argument>
שנקראsleepNightKey
.
כשהמשתמש עובר מ-SleepTrackerFragment
ל-SleepQualityFragment,
, האפליקציה תעבירsleepNightKey
ל-SleepQualityFragment
ללילה שצריך לעדכן.
שלב 2: הוספת ניווט למעקב אחר איכות השינה
תרשים הניווט כבר כולל את הנתיבים מSleepTrackerFragment
אל SleepQualityFragment
ובחזרה. עם זאת, עדיין לא נכתב קוד ל-click handlers שמטמיעים את הניווט מקטע אחד לקטע הבא. מוסיפים את הקוד הזה עכשיו ב-ViewModel
.
ב-click handler, מגדירים LiveData
שמשתנה כשרוצים שהאפליקציה תנווט ליעד אחר. הקטע מתייחס לLiveData
. כשהנתונים משתנים, הפראגמנט עובר ליעד ומעדכן את מודל התצוגה שהוא סיים, מה שגורם לאיפוס של משתנה המצב.
- פתיחת
SleepTrackerViewModel
. צריך להוסיף ניווט כך שכשהמשתמש יקיש על הלחצן Stop, האפליקציה תנווט אלSleepQualityFragment
כדי לאסוף דירוג איכות. - ב-
SleepTrackerViewModel
, יוצריםLiveData
שמשתנה כשרוצים שהאפליקציה תעבור אלSleepQualityFragment
. משתמשים בהסתרת מידע כדי לחשוף רק גרסה שאפשר לקבל שלLiveData
אלViewModel
.
אפשר להציב את הקוד הזה בכל מקום ברמה העליונה של גוף המחלקה.
private val _navigateToSleepQuality = MutableLiveData<SleepNight>()
val navigateToSleepQuality: LiveData<SleepNight>
get() = _navigateToSleepQuality
- מוסיפים פונקציה
doneNavigating()
שמאפסת את המשתנה שמפעיל את הניווט.
fun doneNavigating() {
_navigateToSleepQuality.value = null
}
- ב-click handler של הלחצן Stop,
onStopTracking()
, מפעילים את הניווט אלSleepQualityFragment
. מגדירים את המשתנה _navigateToSleepQuality
בסוף הפונקציה כדבר האחרון בתוך הבלוקlaunch{}
. הערה: המשתנה הזה מוגדר לערךnight
. כשהמשתנה הזה מקבל ערך, האפליקציה עוברת אלSleepQualityFragment
, ומעבירה את הלילה.
_navigateToSleepQuality.value = oldNight
- ה-
SleepTrackerFragment
צריך לעקוב אחרי _navigateToSleepQuality
כדי שהאפליקציה תדע מתי לנווט. ב-SleepTrackerFragment
, ב-onCreateView()
, מוסיפים משקיף ל-navigateToSleepQuality()
. שימו לב: הייבוא של זה לא חד-משמעי, ואתם צריכים לייבא אתandroidx.lifecycle.Observer
.
sleepTrackerViewModel.navigateToSleepQuality.observe(this, Observer {
})
- בתוך בלוק הצופה, עוברים ומעבירים את המזהה של הלילה הנוכחי, ואז קוראים ל-
doneNavigating()
. אם הייבוא לא ברור, מייבאים אתandroidx.navigation.fragment.findNavController
.
night ->
night?.let {
this.findNavController().navigate(
SleepTrackerFragmentDirections
.actionSleepTrackerFragmentToSleepQualityFragment(night.nightId))
sleepTrackerViewModel.doneNavigating()
}
- מפתחים ומריצים את האפליקציה. מקישים על התחלה ואז על עצירה, ועוברים למסך
SleepQualityFragment
. כדי לחזור, משתמשים בלחצן 'הקודם' של המערכת.
במשימה הזו, מקליטים את איכות השינה וחוזרים אל קטע השינה. הערך המעודכן אמור להופיע למשתמש באופן אוטומטי. צריך ליצור ViewModel
וViewModelFactory
, ולעדכן את SleepQualityFragment
.
שלב 1: יצירת ViewModel ו-ViewModelFactory
- בחבילה
sleepquality
, יוצרים או פותחים את SleepQualityViewModel.kt. - יוצרים מחלקה
SleepQualityViewModel
שמקבלתsleepNightKey
ומסד נתונים כארגומנטים. בדיוק כמו שעשיתם בשלבSleepTrackerViewModel
, אתם צריכים להעביר אתdatabase
מהמפעל. צריך גם להעביר אתsleepNightKey
מהניווט.
class SleepQualityViewModel(
private val sleepNightKey: Long = 0L,
val database: SleepDatabaseDao) : ViewModel() {
}
- בתוך המחלקה
SleepQualityViewModel
, מגדירים אתJob
ואתuiScope
, ומבטלים את ההגדרה שלonCleared()
.
private val viewModelJob = Job()
private val uiScope = CoroutineScope(Dispatchers.Main + viewModelJob)
override fun onCleared() {
super.onCleared()
viewModelJob.cancel()
}
- כדי לחזור אל
SleepTrackerFragment
באמצעות אותו דפוס כמו למעלה, מצהירים על_navigateToSleepTracker
. מטמיעים אתnavigateToSleepTracker
ואתdoneNavigating()
.
private val _navigateToSleepTracker = MutableLiveData<Boolean?>()
val navigateToSleepTracker: LiveData<Boolean?>
get() = _navigateToSleepTracker
fun doneNavigating() {
_navigateToSleepTracker.value = null
}
- יוצרים handler של קליק אחד,
onSetSleepQuality()
, לכל התמונות של איכות השינה.
משתמשים באותו דפוס של קורוטינה כמו ב-codelab הקודם:
- מפעילים קורוטינה ב-
uiScope
ועוברים למפיץ של קלט/פלט. - קבלת
tonight
באמצעותsleepNightKey
. - מגדירים את איכות השינה.
- מעדכנים את מסד הנתונים.
- הפעלת ניווט.
שימו לב שדוגמת הקוד שבהמשך מבצעת את כל העבודה ב-click 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
}
}
- בחבילה
sleepquality
, יוצרים או פותחים אתSleepQualityViewModelFactory.kt
ומוסיפים את המחלקהSleepQualityViewModelFactory
, כמו שמוצג בהמשך. בשיעור הזה נעשה שימוש בגרסה של אותו קוד boilerplate שראיתם קודם. כדאי לבדוק את הקוד לפני שממשיכים.
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
- פתיחת
SleepQualityFragment.kt
. - ב-
onCreateView()
, אחרי שמקבלים אתapplication
, צריך לקבל אתarguments
שמגיעה עם הניווט. הארגומנטים האלה מופיעים ב-SleepQualityFragmentArgs
. צריך לחלץ אותם מהחבילה.
val arguments = SleepQualityFragmentArgs.fromBundle(arguments!!)
- בשלב הבא, מקבלים את
dataSource
.
val dataSource = SleepDatabase.getInstance(application).sleepDatabaseDao
- יוצרים מפעל ומעבירים את
dataSource
ואתsleepNightKey
.
val viewModelFactory = SleepQualityViewModelFactory(arguments.sleepNightKey, dataSource)
- קבלת הפניה למסמך או קישור בסך
ViewModel
.
val sleepQualityViewModel =
ViewModelProviders.of(
this, viewModelFactory).get(SleepQualityViewModel::class.java)
- מוסיפים את
ViewModel
לאובייקט הקישור. (אם מופיעה שגיאה באובייקט של הקישור, אפשר להתעלם ממנה בשלב הזה).
binding.sleepQualityViewModel = sleepQualityViewModel
- מוסיפים את הצופה. כשמופיעה בקשה, מייבאים את
androidx.lifecycle.Observer
.
sleepQualityViewModel.navigateToSleepTracker.observe(this, Observer {
if (it == true) { // Observed state is true.
this.findNavController().navigate(
SleepQualityFragmentDirections.actionSleepQualityFragmentToSleepTrackerFragment())
sleepQualityViewModel.doneNavigating()
}
})
שלב 3: מעדכנים את קובץ הפריסה ומריצים את האפליקציה
- פותחים את קובץ הפריסה
fragment_sleep_quality.xml
. בבלוק<data>
, מוסיפים משתנה ל-SleepQualityViewModel
.
<data>
<variable
name="sleepQualityViewModel"
type="com.example.android.trackmysleepquality.sleepquality.SleepQualityViewModel" />
</data>
- לכל אחת משש התמונות של איכות השינה, מוסיפים click handler כמו זה שמופיע למטה. התאימו את דירוג האיכות לתמונה.
android:onClick="@{() -> sleepQualityViewModel.onSetSleepQuality(5)}"
- מנקים את הפרויקט ובונים אותו מחדש. הפעולה הזו אמורה לפתור את כל השגיאות באובייקט הקישור. אחרת, מנקים את המטמון (File > Invalidate Caches / Restart) ובונים מחדש את האפליקציה.
מעולה! הרגע יצרתם אפליקציית מסד נתונים מלאה של Room
באמצעות קורוטינות.
עכשיו האפליקציה פועלת בצורה מצוינת. המשתמש יכול להקיש על התחלה ועל עצירה כמה פעמים שרוצה. כשהמשתמש מקיש על הפסקה, הוא יכול להזין את איכות השינה. כשהמשתמש מקיש על ניקוי, כל הנתונים מנוקים בשקט ברקע. עם זאת, כל הלחצנים תמיד מופעלים ואפשר ללחוץ עליהם, מה שלא גורם לאפליקציה לקרוס, אבל מאפשר למשתמשים ליצור לילות שינה לא מלאים.
במשימה האחרונה נלמד איך להשתמש במיפוי טרנספורמציות כדי לנהל את הנראות של הלחצנים, כך שהמשתמשים יוכלו לבחור רק את האפשרות הנכונה. אפשר להשתמש בשיטה דומה כדי להציג הודעה ידידותית אחרי שכל הנתונים נמחקו.
שלב 1: עדכון מצבי הכפתורים
הרעיון הוא להגדיר את מצב הלחצן כך שבהתחלה רק הלחצן התחלה יהיה מופעל, כלומר ניתן ללחוץ עליו.
אחרי שהמשתמש מקיש על התחלה, הכפתור עצירה מופעל והכפתור התחלה מושבת. הלחצן ניקוי מופעל רק אם יש נתונים במסד הנתונים.
- פותחים את קובץ הפריסה
fragment_sleep_tracker.xml
. - מוסיפים את המאפיין
android:enabled
לכל לחצן. המאפייןandroid:enabled
הוא ערך בוליאני שמציין אם הלחצן מופעל או לא. (אפשר להקיש על לחצן מופעל, אבל אי אפשר להקיש על לחצן מושבת). נותנים למאפיין את הערך של משתנה מצב שנגדיר עוד מעט.
start_button
:
android:enabled="@{sleepTrackerViewModel.startButtonVisible}"
stop_button
:
android:enabled="@{sleepTrackerViewModel.stopButtonVisible}"
clear_button
:
android:enabled="@{sleepTrackerViewModel.clearButtonVisible}"
- פותחים את
SleepTrackerViewModel
ויוצרים שלושה משתנים תואמים. מקצים לכל משתנה טרנספורמציה שבודקת אותו.
- הלחצן התחלה צריך להיות זמין כשערך המשתנה
tonight
הואnull
. - הלחצן Stop (עצירה) צריך להיות זמין כשהערך של
tonight
הוא לאnull
. - הלחצן ניקוי צריך להיות זמין רק אם
nights
, ומכאן גם מסד הנתונים, מכיל נתוני שינה.
val startButtonVisible = Transformations.map(tonight) {
it == null
}
val stopButtonVisible = Transformations.map(tonight) {
it != null
}
val clearButtonVisible = Transformations.map(nights) {
it?.isNotEmpty()
}
- מריצים את האפליקציה ומתנסים בלחצנים.
שלב 2: שימוש בחטיף כדי להודיע למשתמש
אחרי שהמשתמש מוחק את מסד הנתונים, מציגים לו אישור באמצעות הווידג'ט Snackbar
. סרגל אינטראקטיבי מספק משוב קצר על פעולה באמצעות הודעה בתחתית המסך. סרגל החטיפים נעלם אחרי פרק זמן קצוב לתפוגה, אחרי אינטראקציה של המשתמש במקום אחר במסך או אחרי שהמשתמש מחליק את סרגל החטיפים אל מחוץ למסך.
הצגת הסנאקבר היא משימה שקשורה לממשק המשתמש, והיא צריכה להתבצע ב-fragment. ההחלטה להציג את חטיף המידע מתקבלת ב-ViewModel
. כדי להגדיר ולהפעיל סנאקבר כשהנתונים נמחקים, אפשר להשתמש באותה טכניקה שמשמשת להפעלת ניווט.
- ב-
SleepTrackerViewModel
, יוצרים את האירוע המקופסל.
private var _showSnackbarEvent = MutableLiveData<Boolean>()
val showSnackBarEvent: LiveData<Boolean>
get() = _showSnackbarEvent
- לאחר מכן מטמיעים את
doneShowingSnackbar()
.
fun doneShowingSnackbar() {
_showSnackbarEvent.value = false
}
- ב-
SleepTrackerFragment
, ב-onCreateView()
, מוסיפים משקיף:
sleepTrackerViewModel.showSnackBarEvent.observe(this, Observer { })
- בתוך בלוק ה-observer, מציגים את ה-snackbar ומאפסים את האירוע באופן מיידי.
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()
}
- ב-
SleepTrackerViewModel
, מפעילים את האירוע בשיטהonClear()
. כדי לעשות זאת, מגדירים את ערך האירוע ל-true
בתוך הבלוקlaunch
:
_showSnackbarEvent.value = true
- יוצרים ומריצים את האפליקציה.
פרויקט Android Studio: TrackMySleepQualityFinal
הטמעת מעקב אחר איכות השינה באפליקציה הזו היא כמו השמעה של יצירה מוזיקלית מוכרת בסולם חדש. הפרטים משתנים, אבל הדפוס הבסיסי של מה שעשיתם ב-codelab הקודם בשיעור הזה נשאר זהה. ההיכרות עם הדפוסים האלה מאפשרת לתכנת הרבה יותר מהר, כי אפשר לעשות שימוש חוזר בקוד מאפליקציות קיימות. אלה חלק מהדפוסים שבהם השתמשנו בקורס הזה עד עכשיו:
- יוצרים
ViewModel
וViewModelFactory
ומגדירים מקור נתונים. - הפעלת ניווט. כדי להפריד בין הבעיות, כדאי להציב את click handler במודל התצוגה ואת הניווט בקטע.
- משתמשים באנקפסולציה עם
LiveData
כדי לעקוב אחרי שינויים במצב ולהגיב להם. - שימוש בטרנספורמציות עם
LiveData
. - יצירת מסד נתונים יחיד.
- הגדרת קורוטינות לפעולות במסד נתונים.
הפעלת ניווט
אתם מגדירים קובץ ניווט עם נתיבי ניווט אפשריים בין פרגמנטים. יש כמה דרכים להפעיל ניווט מקטע אחד לקטע הבא. למשל:
- הגדרת רכיבי handler של
onClick
להפעלת ניווט אל קטע יעד. - לחלופין, כדי להפעיל את הניווט מקטע אחד לקטע הבא:
- מגדירים ערך של
LiveData
כדי לתעד אם הניווט צריך להתבצע. - מצרפים אובייקט Observer לערך
LiveData
. - לאחר מכן, הקוד משנה את הערך הזה בכל פעם שצריך להפעיל ניווט או כשהניווט מסתיים.
הגדרת המאפיין android:enabled
- המאפיין
android:enabled
מוגדר ב-TextView
ומועבר בירושה לכל מחלקות המשנה, כוללButton
. - המאפיין
android:enabled
קובע אםView
מופעל או לא. המשמעות של 'מופעל' משתנה בהתאם למחלקת המשנה. לדוגמה, אם התכונהEditText
לא מופעלת, המשתמש לא יכול לערוך את הטקסט שמופיע בתוכה, ואם התכונהButton
לא מופעלת, המשתמש לא יכול להקיש על הלחצן. - המאפיין
enabled
שונה מהמאפייןvisibility
. - אפשר להשתמש במיפוי טרנספורמציות כדי להגדיר את הערך של מאפיין
enabled
של לחצנים על סמך המצב של אובייקט או משתנה אחר.
נקודות נוספות שמוסברות ב-Codelab הזה:
- כדי להפעיל התראות למשתמש, אפשר להשתמש באותה טכניקה שבה משתמשים כדי להפעיל ניווט.
- אפשר להשתמש ב
Snackbar
כדי להודיע למשתמש.
קורס ב-Udacity:
מסמכי תיעוד למפתחי Android:
בקטע הזה מפורטות אפשרויות למשימות ביתיות לתלמידים שעובדים על ה-Codelab הזה כחלק מקורס בהנחיית מדריך. המורה צריך:
- אם צריך, מקצים שיעורי בית.
- להסביר לתלמידים איך להגיש מטלות.
- בודקים את שיעורי הבית.
אנשי ההוראה יכולים להשתמש בהצעות האלה כמה שרוצים, ומומלץ להם להקצות כל שיעורי בית אחרים שהם חושבים שמתאימים.
אם אתם עובדים על ה-codelab הזה לבד, אתם יכולים להשתמש במשימות האלה כדי לבדוק את הידע שלכם.
עונים על השאלות הבאות
שאלה 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"
.
עוברים לשיעור הבא:
קישורים ל-codelabs אחרים בקורס הזה מופיעים בדף הנחיתה של ה-codelabs בנושא יסודות Android Kotlin.