บันทึกข้อมูลในฐานข้อมูลของเครื่องโดยใช้ Room
เป็นส่วนหนึ่งของ Android Jetpack
จัดทุกอย่างให้เป็นระเบียบอยู่เสมอด้วยคอลเล็กชัน
บันทึกและจัดหมวดหมู่เนื้อหาตามค่ากำหนดของคุณ
แอปที่จัดการ Structured Data จำนวนมากจะมีประโยชน์อย่างมากจากการเก็บ Structured Data นั้นไว้ในเครื่อง กรณีการใช้งานที่พบบ่อยที่สุดคือแคชข้อมูลที่เกี่ยวข้องเพื่อให้ผู้ใช้ยังคงเรียกดูเนื้อหานั้นขณะออฟไลน์ได้เมื่ออุปกรณ์เข้าถึงเครือข่ายไม่ได้
ไลบรารีการคงข้อมูลของ Room มีเลเยอร์การแยกแยะระดับบน SQLite เพื่ออนุญาตให้เข้าถึงฐานข้อมูลได้อย่างราบรื่นขณะใช้ความสามารถของ SQLite อย่างเต็มที่ โดย Room มีข้อดีดังต่อไปนี้
- การยืนยันการค้นหา SQL ขณะคอมไพล์
- คําอธิบายประกอบเพื่อความสะดวกที่ช่วยลดโค้ดเทมเพลตที่ซ้ำกันและเกิดข้อผิดพลาดได้ง่าย
- เส้นทางการย้ายข้อมูลฐานข้อมูลที่มีประสิทธิภาพมากขึ้น
ด้วยเหตุนี้ เราจึงขอแนะนําอย่างยิ่งให้คุณใช้ Room แทนการใช้ SQLite API โดยตรง
ตั้งค่า
หากต้องการใช้ Room ในแอป ให้เพิ่ม Dependency ต่อไปนี้ลงในไฟล์ build.gradle
ของแอป
dependencies { val room_version = "2.6.1" implementation("androidx.room:room-runtime:$room_version") // If this project uses any Kotlin source, use Kotlin Symbol Processing (KSP) // See Add the KSP plugin to your project ksp("androidx.room:room-compiler:$room_version") // If this project only uses Java source, use the Java annotationProcessor // No additional plugins are necessary annotationProcessor("androidx.room:room-compiler:$room_version") // optional - Kotlin Extensions and Coroutines support for Room implementation("androidx.room:room-ktx:$room_version") // optional - RxJava2 support for Room implementation("androidx.room:room-rxjava2:$room_version") // optional - RxJava3 support for Room implementation("androidx.room:room-rxjava3:$room_version") // optional - Guava support for Room, including Optional and ListenableFuture implementation("androidx.room:room-guava:$room_version") // optional - Test helpers testImplementation("androidx.room:room-testing:$room_version") // optional - Paging 3 Integration implementation("androidx.room:room-paging:$room_version") }
dependencies { def room_version = "2.6.1" implementation "androidx.room:room-runtime:$room_version" // If this project uses any Kotlin source, use Kotlin Symbol Processing (KSP) // See KSP Quickstart to add KSP to your build ksp "androidx.room:room-compiler:$room_version" // If this project only uses Java source, use the Java annotationProcessor // No additional plugins are necessary annotationProcessor "androidx.room:room-compiler:$room_version" // optional - RxJava2 support for Room implementation "androidx.room:room-rxjava2:$room_version" // optional - RxJava3 support for Room implementation "androidx.room:room-rxjava3:$room_version" // optional - Guava support for Room, including Optional and ListenableFuture implementation "androidx.room:room-guava:$room_version" // optional - Test helpers testImplementation "androidx.room:room-testing:$room_version" // optional - Paging 3 Integration implementation "androidx.room:room-paging:$room_version" }
คอมโพเนนต์หลัก
Room มีองค์ประกอบหลัก 3 อย่าง ได้แก่
- คลาสฐานข้อมูลที่เก็บฐานข้อมูลและทำหน้าที่เป็นจุดเข้าใช้งานหลักสำหรับการเชื่อมต่อพื้นฐานกับข้อมูลที่เก็บไว้ของแอป
- เอนทิตีข้อมูลที่แสดงตารางในฐานข้อมูลของแอป
- ออบเจ็กต์การเข้าถึงข้อมูล (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? )
@Entity public class User { @PrimaryKey public int uid; @ColumnInfo(name = "first_name") public String firstName; @ColumnInfo(name = "last_name") public String lastName; }
ดูข้อมูลเพิ่มเติมเกี่ยวกับเอนทิตีข้อมูลใน Room ได้ที่การกำหนดข้อมูลโดยใช้เอนทิตี Room
ออบเจ็กต์การเข้าถึงข้อมูล (DAO)
โค้ดต่อไปนี้จะกำหนด DAO ชื่อ UserDao
UserDao
มีวิธีการที่แอปส่วนอื่นๆ ใช้เพื่อโต้ตอบกับข้อมูลในตาราง user
@Dao interface UserDao { @Query("SELECT * FROM user") fun getAll(): List<User> @Query("SELECT * FROM user WHERE uid IN (:userIds)") fun loadAllByIds(userIds: IntArray): List<User> @Query("SELECT * FROM user WHERE first_name LIKE :first AND " + "last_name LIKE :last LIMIT 1") fun findByName(first: String, last: String): User @Insert fun insertAll(vararg users: User) @Delete fun delete(user: User) }
@Dao public interface UserDao { @Query("SELECT * FROM user") List<User> getAll(); @Query("SELECT * FROM user WHERE uid IN (:userIds)") List<User> loadAllByIds(int[] userIds); @Query("SELECT * FROM user WHERE first_name LIKE :first AND " + "last_name LIKE :last LIMIT 1") User findByName(String first, String last); @Insert void insertAll(User... users); @Delete void delete(User user); }
ดูข้อมูลเพิ่มเติมเกี่ยวกับ DAO ได้ที่การเข้าถึงข้อมูลโดยใช้ DAO ของ Room
ฐานข้อมูล
โค้ดต่อไปนี้จะกำหนดคลาส AppDatabase
เพื่อเก็บฐานข้อมูล
AppDatabase
กำหนดการกำหนดค่าฐานข้อมูลและทำหน้าที่เป็นจุดเข้าถึงหลักของแอปสำหรับข้อมูลที่เก็บไว้ คลาสฐานข้อมูลต้องเป็นไปตามเงื่อนไขต่อไปนี้
- ชั้นเรียนต้องมีการกำกับเนื้อหาด้วยคำอธิบายประกอบ
@Database
ที่มีอาร์เรย์entities
ที่แสดงรายการเอนทิตีข้อมูลทั้งหมดที่เชื่อมโยงกับฐานข้อมูล - โดยคลาสต้องเป็นคลาสนามธรรมที่ขยายจาก
RoomDatabase
- สําหรับคลาส DAO แต่ละคลาสที่เชื่อมโยงกับฐานข้อมูล คลาสฐานข้อมูลต้องกําหนดเมธอดนามธรรมที่ไม่มีอาร์กิวเมนต์และแสดงผลอินสแตนซ์ของคลาส DAO
@Database(entities = [User::class], version = 1) abstract class AppDatabase : RoomDatabase() { abstract fun userDao(): UserDao }
@Database(entities = {User.class}, version = 1) public abstract class AppDatabase extends RoomDatabase { public abstract UserDao userDao(); }
หมายเหตุ: หากแอปทำงานในกระบวนการเดียว คุณควรทำตามรูปแบบการออกแบบแบบ Singleton เมื่อสร้างอินสแตนซ์ของออบเจ็กต์ AppDatabase
อินสแตนซ์ RoomDatabase
แต่ละรายการมีราคาค่อนข้างสูง และคุณแทบไม่จําเป็นต้องเข้าถึงอินสแตนซ์หลายรายการภายในกระบวนการเดียว
หากแอปทำงานในหลายกระบวนการ ให้ใส่ enableMultiInstanceInvalidation()
ในการเรียกใช้เครื่องมือสร้างฐานข้อมูล วิธีนี้ช่วยให้คุณทำให้ไฟล์ฐานข้อมูลที่แชร์ในกระบวนการหนึ่งเป็นโมฆะได้เมื่อคุณมีอินสแตนซ์ของ AppDatabase
ในกระบวนการแต่ละรายการ และระบบจะนำไปเผยแพร่ไปยังอินสแตนซ์ของ AppDatabase
ในกระบวนการอื่นๆ โดยอัตโนมัติ
การใช้งาน
หลังจากกําหนดเอนทิตีข้อมูล DAO และออบเจ็กต์ฐานข้อมูลแล้ว คุณจะใช้โค้ดต่อไปนี้เพื่อสร้างอินสแตนซ์ของฐานข้อมูลได้
val db = Room.databaseBuilder( applicationContext, AppDatabase::class.java, "database-name" ).build()
AppDatabase db = Room.databaseBuilder(getApplicationContext(), AppDatabase.class, "database-name").build();
จากนั้นคุณจะใช้เมธอดนามธรรมจาก AppDatabase
เพื่อรับอินสแตนซ์ของ DAO ได้ จากนั้น คุณจะใช้เมธอดจากอินสแตนซ์ DAO เพื่อโต้ตอบกับฐานข้อมูลได้ ดังนี้
val userDao = db.userDao() val users: List<User> = userDao.getAll()
UserDao userDao = db.userDao(); List<User> users = userDao.getAll();
แหล่งข้อมูลเพิ่มเติม
ดูข้อมูลเพิ่มเติมเกี่ยวกับ Room ได้ที่แหล่งข้อมูลต่อไปนี้
ตัวอย่าง
Jetcaster is a sample podcast app, built with Jetpack Compose. The goal of the sample is to showcase building with Compose across multiple form factors (mobile, TV, and Wear) and full featured architecture.
To try out this sample app, use the latest These samples showcase different architectural approaches to developing Android apps. In its different branches you'll find the same app (a TODO app) implemented with small differences.
In this branch you'll find:
User Interface built with Jetpack Learn how this app was designed and built in the design case study, architecture learning journey and modularization learning journey.
This is the repository for the Now in Android app. It is a work in progress 🚧.
Now in Android is a fully functionalJetcaster sample 🎙️
Architecture
Now in Android App