ה-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, מגדירים את הערךLiveDatagotoBlueFragment. - ב-
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.