שמירת נתונים במסד נתונים מקומי באמצעות Room בארגז הכלים Android Jetpack.
באפליקציות שמטפלות בכמויות גדולות של נתונים מובְנים, כדאי לשמור את הנתונים האלה באופן מקומי. תרחיש השימוש הנפוץ ביותר הוא שמירת חלקים רלוונטיים של נתונים במטמון, כך שגם אם למכשיר אין גישה לרשת, המשתמשים יוכלו לעיין בתוכן הזה במצב אופליין.
ספריית Room persistence מספקת שכבת הפשטה מעל SQLite כדי לאפשר גישה שוטפת למסד הנתונים תוך ניצול מלא של היכולות של SQLite. באופן ספציפי, Room מספק את היתרונות הבאים:
- אימות של שאילתות SQL בזמן הקימפול.
- הערות נוחות שמצמצמות קוד שחוזר על עצמו (boilerplate) ומועד לשגיאות.
- נתיבים יעילים להעברת מסדי נתונים.
אנחנו ממליצים להשתמש ב-Room במקום להשתמש ישירות בממשקי ה-API של SQLite.
הגדרה
כדי להשתמש ב-Room באפליקציה, מוסיפים את יחסי התלות הבאים לקובץ build.gradle.kts של המודול. בגרסה 3.0 של Room נדרש KSP לעיבוד הערות.
Kotlin
dependencies { val room_version = "3.0.3" implementation("androidx.room3:room3-runtime:$room_version") ksp("androidx.room3:room3-compiler:$room_version") }
Groovy
dependencies { def room_version = "3.0.3" implementation "androidx.room3:room3-runtime:$room_version" ksp "androidx.room3:room3-compiler:$room_version" }
הרכיבים העיקריים
ב-Room יש שלושה רכיבים עיקריים:
- מחלקה של מסד נתונים שמכילה את מסד הנתונים ומשמשת כנקודת הגישה הראשית לחיבור הבסיסי לנתונים שנשמרו באפליקציה.
- ישויות הנתונים שמייצגות טבלאות במסד הנתונים של האפליקציה.
- אובייקטים של גישה לנתונים (DAO) שמספקים פונקציות שהאפליקציה יכולה להשתמש בהן כדי לשלוח שאילתות, לעדכן, להוסיף ולמחוק נתונים במסד הנתונים.
המחלקה של מסד הנתונים מספקת לאפליקציה מופעים של אובייקטי ה-DAO שמשויכים למסד הנתונים הזה. בתמורה, האפליקציה יכולה להשתמש ב-DAO כדי לאחזר נתונים ממסד הנתונים כמופעים של אובייקטים של ישויות נתונים משויכות. האפליקציה יכולה גם להשתמש בישויות הנתונים שהוגדרו כדי לעדכן שורות מהטבלאות המתאימות, או כדי ליצור שורות חדשות להוספה. איור 1 ממחיש את הקשר בין הרכיבים השונים של Room.
הטמעה לדוגמה
בקטע הזה מוצגת דוגמה להטמעה של מסד נתונים ב-Room עם ישות נתונים אחת ו-DAO אחד.
ישות נתונים
הקוד הבא מגדיר ישות נתונים מסוג User. כל מופע של User
מייצג שורה בטבלת user במסד הנתונים של האפליקציה.
@Entity data class User( @PrimaryKey val uid: Int, @ColumnInfo(name = "first_name") val firstName: String, @ColumnInfo(name = "last_name") val lastName: String )
מידע נוסף על ישויות נתונים ב-Room זמין במאמר הגדרת נתונים באמצעות ישויות של Room.
אובייקט גישה לנתונים (DAO)
הקוד הבא מגדיר DAO שנקרא UserDao. הקובץ UserDao מספק את הפונקציות שבהן שאר האפליקציה משתמשת כדי לבצע אינטראקציה עם הנתונים בטבלה user.
@Dao interface UserDao { @Query("SELECT * FROM user") suspend fun getAll(): List<User> @Query("SELECT * FROM user WHERE uid IN (:userIds)") suspend fun loadAllByIds(userIds: IntArray): List<User> @Query( """ SELECT * FROM user WHERE first_name LIKE :first AND last_name LIKE :last LIMIT 1 """ ) suspend fun findByName(first: String, last: String): User @Insert suspend fun insertAll(vararg users: User) @Delete suspend fun delete(user: User) }
מידע נוסף על אובייקטים של גישה לנתונים זמין במאמר גישה לנתונים באמצעות אובייקטים של גישה לנתונים ב-Room.
מסד נתונים
הקוד הבא מגדיר מחלקה AppDatabase להחזקת מסד הנתונים.
AppDatabase מגדיר את תצורת מסד הנתונים ומשמש כנקודת הגישה העיקרית של האפליקציה לנתונים שנשמרו. המחלקות במסד הנתונים צריכות לעמוד בתנאים הבאים:
- הכיתה צריכה להיות מסומנת בהערה
@Databaseשכוללת מערךentitiesשמפרט את כל ישויות הנתונים שמשויכות למסד הנתונים. - המחלקה חייבת להיות מחלקה מופשטת שמרחיבה את
RoomDatabase. - לכל מחלקת DAO שמשויכת למסד הנתונים, מחלקת מסד הנתונים צריכה להגדיר פונקציה מופשטת שלא מקבלת ארגומנטים ומחזירה מופע של מחלקת ה-DAO.
@Database(entities = [User::class], version = 1) abstract class AppDatabase : RoomDatabase() { abstract fun userDao(): UserDao }
הערה: אם האפליקציה שלכם פועלת בתהליך יחיד, צריך לפעול לפי תבנית העיצוב של singleton כשיוצרים מופע של אובייקט AppDatabase. כל מופע של RoomDatabase יקר למדי, ובדרך כלל לא צריך גישה לכמה מופעים בתהליך אחד.
אם האפליקציה פועלת בכמה תהליכים, צריך לכלול את enableMultiInstanceInvalidation() בקריאה ל-database builder. כך, כשיש מופע של AppDatabase בכל תהליך, אפשר לבטל את קובץ מסד הנתונים המשותף בתהליך אחד, והביטול הזה מועבר באופן אוטומטי למופעים של AppDatabase בתהליכים אחרים.
שימוש
אחרי שמגדירים את ישות הנתונים, את ה-DAO ואת אובייקט מסד הנתונים, אפשר להשתמש בקוד הבא כדי ליצור מופע של מסד הנתונים:
val db = Room.databaseBuilder<AppDatabase>(applicationContext, "database-name") .setDriver(AndroidSQLiteDriver()) .build()
אחר כך אפשר להשתמש בפונקציות המופשטות מ-AppDatabase כדי לקבל מופע של DAO. אחר כך, תוכלו להשתמש בפונקציות ממופע ה-DAO כדי ליצור אינטראקציה עם מסד הנתונים:
val userDao = db.userDao() val users: List<User> = userDao.getAll()
מקורות מידע נוספים
איפה אפשר למצוא מידע נוסף על Room?