Lab Lab זה הוא חלק מקורס Android Kotlin Fundamentals. כדי להפיק את המקסימום מהקורס הזה, יש לפעול ברצף לפי קודי שיעור ה-Lab. כל שיעורי Lab של הקורסים מופיעים בדף הנחיתה של Lab Kotlin Fundamentals ל-Android Lab.
מבוא
רוב האפליקציות כוללות נתונים שצריכים להישמר, גם אחרי שהמשתמש סוגר את האפליקציה. לדוגמה, האפליקציה עשויה לאחסן פלייליסט, מלאי פריטים במשחק, רשומות של הוצאות והכנסה, קטלוג של קבוצות זיהוי או נתוני שינה לאורך זמן. בדרך כלל, צריך להשתמש במסד נתונים כדי לאחסן נתונים רציפים.
Room
היא ספריית מסד נתונים שהיא חלק מ-Jetpack של Android. Room
מטפלת במשימות רבות של הגדרה והגדרה של מסד נתונים, ומאפשרת לאפליקציה ליצור אינטראקציה עם מסד הנתונים באמצעות קריאות רגילות לפונקציה. מאחורי הקלעים, Room
היא שכבת הפשטה מעל מסד נתונים של SQLite. המילון של Room
' והתחביר של השאילתות עבור שאילתות מורכבות יותר, פועלים לפי המודל של SQLite.
התמונה הבאה ממחישה איך מסד הנתונים של Room
מתאים לארכיטקטורה הכוללת המומלצת בקורס הזה.
דברים שחשוב לדעת
כדאי שתכירו את:
- בניית ממשק משתמש בסיסי (UI) לאפליקציה ל-Android
- שימוש בפעילויות, מקטעים וצפיות.
- ניווט בין מקטעים
- הצגה של דגמים, מפעלים לבניית מודלים של צפייה,
LiveData
וגם הצופים שלה. הנושאים האלו של רכיבי הארכיטקטורה מכסים בשיעור Lab מוקדם יותר בקורס הזה. - הבנה בסיסית של מסדי נתונים של SQL ואת שפת SQLite. ב-SQLite Primer אפשר למצוא סקירה כללית או רענון מהירים.
מה תלמדו
- איך ליצור מסד נתונים עם
Room
ולבצע פעולות לגביו כדי לשמור על נתונים. - איך יוצרים סיווג נתונים שמגדיר טבלה בטבלה.
- איך להשתמש באובייקט גישה לנתונים (DAO) כדי למפות פונקציות של Kotlin לשאילתות SQL.
- איך בודקים אם מסד הנתונים עובד.
הפעולות שתבצעו:
- יצירת מסד נתונים
Room
עם ממשק לנתוני שינה בלילה. - בודקים את מסד הנתונים באמצעות הבדיקות שסופקו.
ב-codelab זה בונים את מסד הנתונים של אפליקציה שעוקבת אחר איכות השינה. האפליקציה משתמשת במסד הנתונים כדי לאחסן נתוני שינה לאורך זמן.
לאפליקציה יש שני מסכים, המיוצגים על ידי מקטעים, כפי שמוצג באיור למטה.
במסך הראשון, שנמצא מימין, יש לחצנים להפעלה ולהפסקה של המעקב. במסך מוצגים כל נתוני השינה של המשתמש. לחצן הניקוי מוחק באופן סופי את כל הנתונים שהאפליקציה אספה עבור המשתמש.
המסך השני, שמוצג בצד שמאל, הוא בחירה בדירוג של איכות השינה. באפליקציה, הדירוג מיוצג באופן מספרי. למטרות פיתוח, האפליקציה מציגה גם את סמלי הפנים ואת הסמלים המספריים שלהם.
התהליך של המשתמש הוא:
- המשתמש פותח את האפליקציה ומוצג לו מסך מעקב אחר השינה.
- המשתמש מקיש על הלחצן התחלה. פעולה זו מתעדת את שעת ההתחלה ומציגה אותה. הלחצן התחלה מושבת, והלחצן עצירה מופעל.
- המשתמש מקיש על הלחצן עצירה. פעולה זו מתעדת את שעת הסיום ופותחים את מסך איכות השינה.
- המשתמש בוחר בסמל של איכות השינה. המסך נסגר, ובמסך המעקב מוצגות שעת הסיום ואיכות השינה. הלחצן עצירה מושבת והלחצן התחלה מופעל. האפליקציה מוכנה ללילה אחר.
- הלחצן ניקוי מופעל בכל פעם שיש נתונים במסד הנתונים. כשהמשתמש מקיש על הלחצן ניקוי, כל הנתונים שלו נמחקים ללא צורך בפעולה נוספת. אין הודעה "האם אתה בטוח?"
האפליקציה הזו משתמשת בארכיטקטורה פשוטה, כפי שמפורט בהמשך בהקשר של הארכיטקטורה המלאה. האפליקציה משתמשת רק ברכיבים הבאים:
- בקר ממשק משתמש
- הצגת הדגם ו-
LiveData
- מסד נתונים של חדר
שלב 1: הורדה והפעלה של האפליקציה למתחילים
- מורידים את האפליקציה TrackMySleepquality-Starter מ-GitHub.
- יש לבנות את האפליקציה ולהפעיל אותה. האפליקציה מציגה את ממשק המשתמש של קטע הקוד
SleepTrackerFragment
, אך אין נתונים. הלחצנים לא מגיבים להקשות.
שלב 2: בדיקת האפליקציה למתחילים
- עיינו בקבצים של Gradle:
- קובץ Gradle של הפרויקט
בקובץbuild.gradle
ברמת הפרויקט, שימו לב למשתנים המציינים גרסאות של ספריות. הגרסאות שנמצאות בשימוש באפליקציה למתחילים פועלות היטב, ועובדות היטב עם האפליקציה הזו. עד שקוד ה-Lab הזה יסתיים, ייתכן שמערכת Android Studio תבקש מכם לעדכן חלק מהגרסאות. אם אתם רוצים לעדכן את הגרסאות שנמצאות באפליקציה או להישאר באפליקציה, עליכם להחליט אם הן יעודכנו. אם תיתקלו בשגיאות אוסף של "range" השתמשו בשילוב של גרסאות ספרייה שבהן נעשה שימוש באפליקציית הפתרון הסופית. - קובץ Gradle של המודול. שימו לב ליחסי תלות של כל הספריות של Jetpack ל-Android, כולל
Room
, וכן לתלויות בכל השגרות.
- מומלץ לעיין בחבילות ובממשק המשתמש. האפליקציה מורכבת מפונקציונליות. החבילה מכילה קובצי placeholder שאליהם מוסיפים קוד בכל סדרת מעבדות הקוד הזו.
- החבילה
database
, לכל הקוד הקשור למסד הנתונים שלRoom
. - החבילות
sleepquality
ו-sleeptracker
מכילות את המקטע, את חלק מהדגם ואת מודל התצוגה בכל מסך.
- הסתכלו בקובץ
Util.kt
, המכיל פונקציות שעוזרות להציג נתוני איכות שינה. חלק מהקודים מציינים תגובות מפני שהם מפנים למודל תצוגה שיצרת מאוחר יותר. - יש לבדוק את תיקיית Android (
SleepDatabaseTest.kt
). אפשר להשתמש בבדיקה הזו כדי לוודא שמסד הנתונים פועל כראוי.
ב-Android, הנתונים מיוצגים במחלקות נתונים, וניתן לגשת אליהם ולשנות אותם באמצעות הקריאות לפונקציות. עם זאת, בעולם מסד הנתונים צריך ישויות ושאילתות.
- ישות מייצגת אובייקט או מושג, ואת המאפיינים שלו, כדי לאחסן אותו במסד הנתונים. מחלקה של ישות מגדירה טבלה, וכל מופע של המחלקה הזו מייצג שורה בטבלה. כל נכס מגדיר עמודה. באפליקציה, הישות תשהה מידע על לילה מסוים.
- שאילתה היא בקשה לקבלת נתונים או מידע מטבלה של מסד נתונים או שילוב של טבלאות, או בקשה לביצוע פעולה בנתונים. שאילתות נפוצות הן קבלה, הוספה ועדכון של ישויות. לדוגמה: אפשר להריץ שאילתה לגבי כל הלילות שנרשמו בשינה, ממוינים לפי שעת ההתחלה.
Room
עושה את כל המאמצים הדרושים כדי לעבור ממחלקות הנתונים של Kotlin לישויות שניתן לשמור בטבלאות SQL, ומהצהרות פונקציות ועד שאילתות SQL.
יש להגדיר כל ישות כסיווג נתונים עם הערות, ואת האינטראקציות כממשק עם הערות: אובייקט גישה לנתונים (DAO). Room
משתמש בכיתות האלה עם הערות כדי ליצור טבלאות במסד הנתונים, ושאילתות שפועלות במסד הנתונים.
שלב 1: יצירת ישות ב-SleepNight
במשימה הזו אתם מגדירים לילה אחד של שינה בתור סיווג נתונים עם הערות.
עבור לילה אחד של שינה, יש לתעד את שעת ההתחלה, שעת הסיום ודירוג איכות.
בנוסף, נדרש מזהה כדי לזהות את הלילה באופן ייחודי.
- בחבילה של
database
, מאתרים את הקובץSleepNight.kt
ופותחים אותו. - צריך ליצור את סיווג הנתונים
SleepNight
עם פרמטרים למזהה, שעת התחלה (באלפיות שנייה), שעת סיום (באלפיות שנייה) ודירוג מספרי של איכות השינה.
- צריך להפעיל את
sleepQuality
, לכן יש להגדיר אותו כ--1
. סימן זה לא נאסף נתוני איכות. - צריך גם להפעיל את שעת הסיום. יש להגדיר אותו לשעת ההתחלה כדי לציין שעדיין לא תועדה שעת סיום.
data class SleepNight(
var nightId: Long = 0L,
val startTimeMilli: Long = System.currentTimeMillis(),
var endTimeMilli: Long = startTimeMilli,
var sleepQuality: Int = -1
)
- לפני הצהרת הכיתה, מוסיפים הערות לכיתה עם הנתונים
@Entity
. מה שם הטבלהdaily_sleep_quality_table
? הארגומנט שלtableName
הוא אופציונלי, אבל מומלץ. ניתן לחפש ארגומנטים אחרים בתיעוד.
אם מתבקשים, מייבאים אתEntity
ואת כל שאר ההערות מהספרייהandroidx
.
@Entity(tableName = "daily_sleep_quality_table")
data class SleepNight(...)
- כדי לזהות את
nightId
כמפתח ראשי, יש להוסיף הערה לנכסnightId
באמצעות@PrimaryKey
. יש להגדיר את הפרמטרautoGenerate
לערךtrue
כדי שמערכתRoom
תיצור את המזהה לכל ישות. כך ניתן להבטיח שהמזהה של כל לילה הוא ייחודי.
@PrimaryKey(autoGenerate = true)
var nightId: Long = 0L,...
- סימון הערות בשאר הנכסים באמצעות
@ColumnInfo
. אפשר להתאים אישית את שמות הנכסים באמצעות הפרמטרים הבאים:
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "daily_sleep_quality_table")
data class SleepNight(
@PrimaryKey(autoGenerate = true)
var nightId: Long = 0L,
@ColumnInfo(name = "start_time_milli")
val startTimeMilli: Long = System.currentTimeMillis(),
@ColumnInfo(name = "end_time_milli")
var endTimeMilli: Long = startTimeMilli,
@ColumnInfo(name = "quality_rating")
var sleepQuality: Int = -1
)
- לבנות ולהפעיל את הקוד כדי לוודא שאין בו שגיאות.
במשימה הזו מגדירים אובייקט גישה לנתונים (DAO). ב-Android, פלטפורמת DAO מספקת שיטות נוחות להוספה, למחיקה ולעדכון של מסד הנתונים.
כשמשתמשים במסד נתונים Room
, אפשר לשלוח שאילתות למסד הנתונים על ידי הגדרה וקריאה של פונקציות Kotlin בקוד שלך. פונקציות Kotlin אלה ממופות לשאילתות SQL. המיפויים האלה מוגדרים ב-DAO באמצעות הערות, והמערכת Room
יוצרת את הקוד הנדרש.
נניח שה-DAO הוא הגדרת ממשק מותאם אישית לגישה למסד הנתונים.
עבור פעולות נפוצות במסד הנתונים, הספרייה Room
מספקת הערות נוחות, כמו @Insert
, @Delete
ו-@Update
. בכל השאר יש הערה אחת (@Query
). ניתן לכתוב כל שאילתה שנתמכת על ידי SQLite.
כבונוס, כשתיצרו את השאילתות ב-Android Studio, המהדר יבדוק את שאילתות ה-SQL כדי לאתר שגיאות תחביר.
לגבי מסד הנתונים של לילות השינה, יש לבצע את הפעולות הבאות:
- הוספת לילות חדשים.
- מעדכנים לילה קיים כדי לעדכן את שעת הסיום ודירוג האיכות.
- קבלת לילה ספציפי בהתאם למפתח שלו.
- לקבל את כל הלילות כדי שתוכלו להציג אותם.
- קבלת הלילה האחרון.
- מוחקים את כל הרשומות במסד הנתונים.
שלב 1: יצירת DAO SleepDatabase
- בחבילה של
database
, פותחים אתSleepDatabaseDao.kt
. - לידיעתך, עם ההערה
interface
SleepDatabaseDao
מופיעה ההערה@Dao
. יש להוסיף את כל נקודות ה-DAO עם מילת המפתח@Dao
.
@Dao
interface SleepDatabaseDao {}
- בגוף ההערה של הממשק, מוסיפים הערה אחת (
@Insert
). מתחת ל-@Insert
, מוסיפים פונקציהinsert()
שמקבלת מופע של המחלקהEntity
SleepNight
כארגומנט.
זה הכול. המערכת שלRoom
תיצור את כל הקוד הנדרש כדי להוסיף אתSleepNight
למסד הנתונים. כשמתקשרים אלinsert()
מהקוד של Kotlin, האפליקציהRoom
מפעילה שאילתת SQL כדי להוסיף את הישות למסד הנתונים. (הערה: אפשר לקרוא לפונקציה לכל מה שרוצים).
@Insert
fun insert(night: SleepNight)
- יש להוסיף הערה אחת (
@Update
) עם פונקציהupdate()
עבורSleepNight
. הישות שמעודכנת היא הישות שיש לה את המפתח זהה לזה של הישות המועברת. ניתן לעדכן חלק מהנכסים האחרים של הישות או את כולם.
@Update
fun update(night: SleepNight)
אין הערות נוחות עבור הפונקציונליות שנותרה, ולכן עליך להשתמש בהערה @Query
ולספק שאילתות SQLite.
- יש להוסיף הערה אחת (
@Query
) עם פונקציהget()
שמשתמשת בארגומנטLong
key
ומחזירה ערך NullSleepNight
. תופיע שגיאה של פרמטר חסר.
@Query
fun get(key: Long): SleepNight?
- השאילתה מסופקת כפרמטר של מחרוזת עבור ההערה. הוספת פרמטר אל
@Query
. הגדרתString
כשאילתת SQL.
- יש לבחור את כל העמודות מ-
daily_sleep_quality_table
WHERE
ה-nightId
תואם לארגומנט :key
.
שימו לב ל:key
. אתם משתמשים בסימון הנקודתיים בשאילתה כדי להפנות לארגומנטים בפונקציה.
("SELECT * from daily_sleep_quality_table WHERE nightId = :key")
- יש להוסיף עוד
@Query
עם פונקצייתclear()
ושאילתת SQLite אלDELETE
כל מה שנכלל ב-daily_sleep_quality_table
. שאילתה זו לא מוחקת את הטבלה עצמה.
הערה אחת (@Delete
) מוחקת פריט אחד, ואפשר להשתמש ב-@Delete
כדי להוסיף רשימה של לילות למחיקה. החיסרון הוא שצריך לאחזר או לדעת מה נמצא בטבלה. ההערה@Delete
מצוינת למחיקת רשומות ספציפיות, אבל לא יעילה לניקוי כל הרשומות מהטבלה.
@Query("DELETE FROM daily_sleep_quality_table")
fun clear()
- הוספת
@Query
עם הפונקציהgetTonight()
.SleepNight
מוחזרת על ידיgetTonight()
כביטול, כדי שהפונקציה תטפל במקרה שבו הטבלה ריקה. (הטבלה ריקה בהתחלה, ואחרי שהנתונים נמחקים.)
כדי לקבל "tonight" ממסד הנתונים, כותבים שאילתת SQLite שמחזירה את הרכיב הראשון ברשימה של תוצאות לפי סדר ב-nightId
בסדר יורד. יש להשתמש ב-LIMIT 1
כדי להחזיר רכיב אחד בלבד.
@Query("SELECT * FROM daily_sleep_quality_table ORDER BY nightId DESC LIMIT 1")
fun getTonight(): SleepNight?
- הוספה של
@Query
עם פונקצייתgetAllNights()
:
- בקשו משאילתת SQLite להחזיר את כל העמודות מה-
daily_sleep_quality_table
, בסדר יורד. - יש להחזיר את
getAllNights()
עם רשימה של ישויותSleepNight
כ-LiveData
.Room
שומר עבורך אתLiveData
הזה, כך ש עליך לקבל את הנתונים רק פעם אחת באופן מפורש. - ייתכן שיהיה צורך לייבא את
LiveData
מ-androidx.lifecycle.LiveData
.
@Query("SELECT * FROM daily_sleep_quality_table ORDER BY nightId DESC")
fun getAllNights(): LiveData<List<SleepNight>>
- לא יוצגו שינויים, אבל מומלץ להפעיל את האפליקציה כדי לוודא שאין בה שגיאות.
במשימה הזו, יוצרים מסד נתונים של Room
שמשתמש ב-Entity
וב-DAO שיצרתם במשימה הקודמת.
עליך ליצור כיתה מופשטת של בעל מסד נתונים עם הערות @Database
. לכיתה הזו יש שיטה אחת שיוצרת מופע של מסד הנתונים, אם מסד הנתונים לא קיים, או מחזירה הפניה למסד נתונים קיים.
כדי לקבל מסד נתונים של Room
, צריך מעט מעורבות. לכן, זהו התהליך הכללי לפני שמתחילים בקוד:
- יש ליצור כיתה
public abstract
שלextends RoomDatabase
. כיתה זו אמורה לשמש כבעלי מסד נתונים. הכיתה מופשטת כיRoom
יוצר את ההטמעה עבורך. - מוסיפים הערות לכיתה באמצעות
@Database
. בארגומנטים, עליכם להצהיר על הישויות של מסד הנתונים ולהגדיר את מספר הגרסה. - בתוך אובייקט
companion
, מגדירים שיטה או נכס מופשטים שמחזירהSleepDatabaseDao
. האפליקציהRoom
תיצור את הגוף עבורך. - יש צורך רק במופע אחד של מסד הנתונים של
Room
לכל האפליקציה, לכן צריך להגדיר אתRoomDatabase
כטון יחיד. - כדי ליצור את מסד הנתונים, יש להשתמש בכלי ליצירת מסד נתונים מסוג
Room
'רק אם מסד הנתונים לא קיים. אם לא, יש להחזיר את מסד הנתונים הקיים.
שלב 1: יוצרים את מסד הנתונים
- בחבילה של
database
, פותחים אתSleepDatabase.kt
. - בקובץ, יש ליצור כיתה אחת (
abstract
) שנקראתSleepDatabase
. היא מרחיבת אתRoomDatabase
.
יש להוסיף הערה לכיתה באמצעות@Database
.
@Database()
abstract class SleepDatabase : RoomDatabase() {}
- תופיע שגיאה עבור ישויות ופרמטרים של גרסה חסרים. ההערה
@Database
מחייבת מספר ארגומנטים, כך ש-Room
יוכל לבנות את מסד הנתונים.
- יש לציין את
SleepNight
כפריט היחיד עם רשימתentities
. - קביעת הערך של
version
בתור1
. בכל פעם שמשנים את הסכימה, צריך להגדיל את מספר הגרסה. - יש להגדיר את
exportSchema
בתורfalse
כדי למנוע גיבוי של היסטוריית הגרסאות של הסכימה.
entities = [SleepNight::class], version = 1, exportSchema = false
- מסד הנתונים צריך לדעת על ה-DAO. בתוך גוף הכיתה, יש להצהיר על ערך מופשט שמחזיר את הערך
SleepDatabaseDao
. אפשר ליצור כמה DAOs.
abstract val sleepDatabaseDao: SleepDatabaseDao
- מתחתיו, מגדירים אובייקט
companion
. האובייקט הנלווה מאפשר ללקוחות לגשת לשיטות ליצירה או לשליפה של מסד הנתונים בלי ליצור כיתה מיידית. המטרה היחידה של הכיתה היא לספק מסד נתונים, ולכן אין סיבה ליצור אותה.
companion object {}
- בתוך האובייקט
companion
, מצהירים על משתנה אפשרי לביטול שלINSTANCE
עבור מסד הנתונים ומפעילים אותו ב-null
. המשתנהINSTANCE
תשמור הפניה למסד הנתונים, אחרי יצירת משתנה. כך ניתן למנוע פתיחה חוזרת של חיבורים למסד הנתונים, וזה יקר.
סימון הערות בINSTANCE
באמצעות @Volatile
. הערך של משתנה תנודתי אף פעם לא נשמר במטמון, וכל הכתיבה והקריאה מתבצעות בזיכרון הראשי. כך ניתן לוודא שהערך של INSTANCE
תמיד עדכני וזהה בכל שרשורי הביצוע. פירוש הדבר הוא שהשינויים שבוצעו בשרשור אחד (INSTANCE
) גלויים לכל השרשורים האחרים באופן מיידי, ואתם לא נתקלים במצב שבו, למשל, שני שרשורים מעדכנים כל ישות במטמון כדי ליצור בעיה.
@Volatile
private var INSTANCE: SleepDatabase? = null
- מתחת ל-
INSTANCE
, עדיין בתוך האובייקטcompanion
, יש להגדיר שיטהgetInstance()
עם פרמטרContext
שנדרש לכלי ליצירת מסד נתונים. החזרת סוג שלSleepDatabase
. לא תוצג לך שגיאה כיgetInstance()
לא מחזיר שום דבר.
fun getInstance(context: Context): SleepDatabase {}
- בתוך
getInstance()
, מוסיפים בלוקsynchronized{}
. יש להעביר את הדומייןthis
כדי לגשת להקשר.
מספר שרשורים עשויים לבקש מופע של מסד נתונים בו-זמנית, וכך לקבל שני מסדי נתונים במקום אחד. סביר להניח שהבעיה לא תתרחש באפליקציה לדוגמה הזו, אבל היא תהיה זמינה לאפליקציה מורכבת יותר. גלישת הקוד כדי לקבל את מסד הנתונים אלsynchronized
פירושה שרק שרשור אחד של ביצוע הפעלה יכול להיכנס לבלוק זה של קוד, כך שמסד הנתונים יאופס פעם אחת בלבד.
synchronized(this) {}
- בתוך הבלוק המסונכרן, מעתיקים את הערך הנוכחי של
INSTANCE
למשתנה המקומיinstance
. כך ניתן לנצל את היתרונות של העברה חכמה, הזמינה רק למשתנים מקומיים.
var instance = INSTANCE
- בתוך הבלוק
synchronized
,return instance
בסוף הבלוק שלsynchronized
. התעלמו משגיאה של אי-התאמה בסוג ההחזרה; לא תחזירו Null לאחר השלמת הפעולה.
return instance
- מעל להצהרה ב-
return
, מוסיפים הצהרה מסוגif
כדי לבדוק אם הערךinstance
הוא null, כלומר אין עדיין מסד נתונים.
if (instance == null) {}
- אם הערך
instance
הואnull
, יש להשתמש בבונה מסד הנתונים כדי לקבל מסד נתונים. בגוף של הצהרתif
, יש להפעיל אתRoom.databaseBuilder
ולספק את ההקשר שהעברת, את מחלקת מסד הנתונים ואת שם מסד הנתונים,sleep_history_database
. כדי להסיר את השגיאה, עליך להוסיף אסטרטגיית העברה ו-build()
בשלבים הבאים.
instance = Room.databaseBuilder(
context.applicationContext,
SleepDatabase::class.java,
"sleep_history_database")
- יש להוסיף את שיטת ההעברה הנדרשת לבונה. יש להשתמש ב-
.fallbackToDestructiveMigration()
.
בדרך כלל, עליך לספק אובייקט מיגרציה עם אסטרטגיית מיגרציה כאשר הסכימה משתנה. אובייקט העברה הוא אובייקט המגדיר את האופן שבו לוקחים את כל השורות עם הסכימה הישנה, וממירים אותן לשורות בסכימה החדשה. כך לא יאבדו נתונים. מיגרציה לא נכללת בהיקף של שיעור Lab זה. הפתרון הפשוט הוא להשמיד ולבנות מחדש את מסד הנתונים, כלומר שהנתונים יאבדו.
.fallbackToDestructiveMigration()
- לבסוף, התקשרו אל
.build()
.
.build()
- יש להקצות את
INSTANCE = instance
כשלב האחרון בדוחif
.
INSTANCE = instance
- הקוד הסופי אמור להיראות כך:
@Database(entities = [SleepNight::class], version = 1, exportSchema = false)
abstract class SleepDatabase : RoomDatabase() {
abstract val sleepDatabaseDao: SleepDatabaseDao
companion object {
@Volatile
private var INSTANCE: SleepDatabase? = null
fun getInstance(context: Context): SleepDatabase {
synchronized(this) {
var instance = INSTANCE
if (instance == null) {
instance = Room.databaseBuilder(
context.applicationContext,
SleepDatabase::class.java,
"sleep_history_database"
)
.fallbackToDestructiveMigration()
.build()
INSTANCE = instance
}
return instance
}
}
}
}
- בונים את הקוד ומפעילים אותו.
מעכשיו יש לך את כל האבני הבניין לעבודה עם מסד הנתונים שלך ב-Room
. הקוד הזה מהדר ופועל, אבל אין דרך לדעת אם הוא פועל בפועל. לכן, זה זמן טוב להוסיף כמה בדיקות בסיסיות.
שלב 2: בדיקת מסד הנתונים SleepDatabase
בשלב זה תריץ בדיקות כדי לוודא שמסד הנתונים שלך פועל. כך אפשר לוודא שמסד הנתונים יפעל לפני השימוש בו. הבדיקות שסופקו הן בסיסיות. אם מדובר באפליקציית ייצור, צריך להפעיל את כל הפונקציות והשאילתות בכל DAOs.
האפליקציה למתחילים כוללת תיקיית androidTest. תיקיית androidTest הזו מכילה בדיקות יחידה שמתייחסות להגדרה אינסטרומנטלית ב-Android. זו דרך מהודרת לומר שהבדיקות מחייבות את המסגרת של Android, כך שצריך להריץ את הבדיקות על מכשיר פיזי או וירטואלי. כמובן, אפשר גם ליצור ולהריץ בדיקות יחידה טהור שאינן כוללות את מסגרת Android.
- ב-Android Studio, בתיקייה androidTest, פותחים את הקובץ SleepDatabaseTest.
- כדי לבטל את סימון הקוד, צריך לבחור בכל הקוד לתגובה וללחוץ על מקש הקיצור
Cmd+/
אוControl+/
. - בודקים את הקובץ.
זהו תיאור קצר של קוד הבדיקה, מכיוון שהוא קטע קוד נוסף שאפשר לעשות בו שימוש חוזר:
SleepDabaseTest
הוא שיעור ניסיון.- ההערה
@RunWith
מזהה את מפעיל הבדיקה, שהיא התוכנית שמגדירה ומפעילה את הבדיקות. - במהלך ההגדרה, הפונקציה בעלת ההערה עם
@Before
מתבצעת, והיא יוצרת זיכרוןSleepDatabase
עםSleepDatabaseDao
. "In-memory" פירושו שמסד הנתונים הזה לא נשמר במערכת הקבצים ויימחק לאחר הפעלת הבדיקות. - בנוסף, בעת יצירת מסד הנתונים של הזיכרון, הקוד קורא לשיטה אחרת, הספציפית לבדיקה,
allowMainThreadQueries
. כברירת מחדל, מופיעה שגיאה אם מנסים להריץ שאילתות בשרשור הראשי. השיטה הזו מאפשרת להריץ בדיקות בשרשור הראשי. האפשרות הזו צריכה להתבצע רק במהלך הבדיקה. - בשיטת בדיקה עם הערות
@Test
, אתם יוצרים, מוסיפים ומאחזריםSleepNight
, ומוודאים שהם זהים. אם משהו משתבש, אפשר ליצור חריג. בבדיקה אמיתית, יהיו לכם מספר@Test
שיטות. - אחרי שהבדיקה תסתיים, הפונקציה עם ההערה
@After
תבוצע כדי לסגור את מסד הנתונים.
- לוחצים לחיצה ימנית על קובץ הבדיקה בחלונית Project ובוחרים באפשרות Run 'SleepDatabaseTest'.
- לאחר הפעלת הבדיקות, יש לבדוק בחלונית SleepDatabaseTest שכל הבדיקות עברו.
מכיוון שכל הבדיקות עברו בהצלחה, עכשיו אתם יודעים כמה דברים:
- מסד הנתונים נוצר כראוי.
- אפשר להוסיף
SleepNight
למסד הנתונים. - אפשר להחזיר את
SleepNight
. - ל-
SleepNight
יש את הערך הנכון עבור האיכות.
פרויקט ב-Android Studio: TrackMySleepquality RoomAndTesting
כשבודקים מסד נתונים, צריך ליישם את כל השיטות המוגדרות ב-DAO. כדי להשלים את הבדיקות, צריך להוסיף ולבצע בדיקות כדי ליישם את שיטות DAO האחרות.
- הגדרת הטבלאות בתור מחלקות נתונים עם הערות ב-
@Entity
. הגדרת מאפיינים עם הערות באמצעות@ColumnInfo
כעמודות בטבלאות. - הגדרה של אובייקט גישה לנתונים (DAO) כממשק עם הערות באמצעות
@Dao
. ה-DAO ממופה פונקציות של Kotlin לשאילתות מסוג מסד נתונים. - מומלץ להשתמש בהערות כדי להגדיר את הפונקציות
@Insert
,@Delete
ו-@Update
. - להשתמש בהערה
@Query
עם מחרוזת שאילתה של SQLite כפרמטר לכל שאילתה אחרת. - צריך ליצור מחלקה מופשטת שכוללת פונקציה
getInstance()
שמחזירה מסד נתונים. - השתמשו בבדיקות אינסטרומנטציה כדי לבדוק שמסד הנתונים ו-DAO שלכם פועלים כמצופה. אפשר להשתמש בבדיקות שסופקו כתבנית.
קורס אוניברסיטה:
מסמכי תיעוד למפתחים של Android:
RoomDatabase
Database
(הערות)- ניתן להשתמש בשאילתות גולמיות עם
Room
Roomdatabase.Builder
- בדיקות
SQLiteDatabase
כיתהDao
Room
ספריית שימור
מסמכים ומאמרים אחרים:
בקטע הזה מפורטות מטלות שיעורי בית אפשריות לתלמידים שעובדים עם קוד Lab הזה, במסגרת קורס בהדרכת מורה. למורה יש אפשרות לבצע את הפעולות הבאות:
- אם צריך, מקצים שיעורי בית.
- ספרו לתלמידים איך מגישים מטלות בשיעורי בית.
- לתת ציונים למטלות שיעורי הבית.
המורים יכולים להשתמש בהצעות האלה כמה שפחות, ומומלץ להקצות להן כל שיעורי בית שדעתם מתאימה להם.
אם אתם עובדים בעצמכם על שיעור הקוד הזה, אתם מוזמנים להשתמש במטלות שיעורי הבית האלה כדי לבחון את הידע שלכם.
מענה על השאלות האלה
שאלה 1
איך מציינים שמחלקה מייצגת ישות לאחסון במסד נתונים של Room
?
- יש להאריך את הכיתה ל-
DatabaseEntity
. - מוסיפים הערות לכיתה באמצעות
@Entity
. - מוסיפים הערות לכיתה באמצעות
@Database
. - יש להרחיב את הכיתה ל-
RoomEntity
ולהוסיף הערות באמצעות@Room
.
שאלה 2
ה-DAO (אובייקט הגישה לנתונים) הוא ממשק שבו Room
משתמש כדי למפות פונקציות של Kotlin לשאילתות מסד נתונים.
איך מציינים שממשק מייצג DAO עבור מסד נתונים של Room
?
- יש להרחיב את הממשק של
RoomDAO
. - יש להאריך את הממשק של
EntityDao
, ואז ליישם את השיטהDaoConnection()
. - מוסיפים הערות לממשק באמצעות
@Dao
. - מוסיפים הערות לממשק באמצעות
@RoomConnection
.
שאלה 3
אילו מההצהרות הבאות נכונות לגבי מסד הנתונים של Room
? צריך לבחור בכל האפשרויות הרלוונטיות.
- אפשר להגדיר טבלאות עבור מסד נתונים מסוג
Room
בתור מחלקות נתונים עם הערות. - אם תחזירו
LiveData
משאילתה,Room
ימשיך לעדכן אתLiveData
אם מתבצעLiveData
. - בכל מסד נתונים מסוג
Room
חייב להיות רק DAO אחד, ואחד בלבד. - כדי לזהות כיתה כמסד נתונים מסוג
Room
, יש להגדיר אותה כמחלקת משנה שלRoomDatabase
ולהוסיף הערות באמצעות@Database
.
שאלה 4
באילו מההערות הבאות ניתן להשתמש בממשק @Dao
? צריך לבחור בכל האפשרויות הרלוונטיות.
@Get
@Update
@Insert
@Query
שאלה 5
איך אפשר לוודא שמסד הנתונים עובד? יש לבחור בכל האפשרויות הרלוונטיות.
- כתיבת אינסטרומנטציות בדיקות.
- ממשיכים לכתוב ולהפעיל את האפליקציה עד שהיא תציג את הנתונים.
- יש להחליף את הקריאות לשיטות בממשק DAO בקריאות לשיטות מקבילות בכיתה
Entity
. - מריצים את הפונקציה
verifyDatabase()
שסופקה על ידי הספרייהRoom
.
מעבר לשיעור הבא:
קישורים למעבדות אחרות של הקוד בקורס הזה זמינים בדף הנחיתה של Android Kotlin Fundamentals Codelabs.