บันทึกข้อมูลในฐานข้อมูลของเครื่องโดยใช้ Room   เป็นส่วนหนึ่งของ Android Jetpack

แอปที่จัดการ Structured Data จำนวนมากจะมีประโยชน์อย่างมากจากการเก็บ Structured Data นั้นไว้ในเครื่อง กรณีการใช้งานที่พบบ่อยที่สุดคือแคชข้อมูลที่เกี่ยวข้องเพื่อให้ผู้ใช้ยังคงเรียกดูเนื้อหานั้นขณะออฟไลน์ได้เมื่ออุปกรณ์เข้าถึงเครือข่ายไม่ได้

ไลบรารีการคงข้อมูลของ Room มีเลเยอร์การแยกแยะระดับบน SQLite เพื่ออนุญาตให้เข้าถึงฐานข้อมูลได้อย่างราบรื่นขณะใช้ความสามารถของ SQLite อย่างเต็มที่ โดย Room มีข้อดีดังต่อไปนี้

  • การยืนยันการค้นหา SQL ขณะคอมไพล์
  • คําอธิบายประกอบเพื่อความสะดวกที่ช่วยลดโค้ดเทมเพลตที่ซ้ำกันและเกิดข้อผิดพลาดได้ง่าย
  • เส้นทางการย้ายข้อมูลฐานข้อมูลที่มีประสิทธิภาพมากขึ้น

ด้วยเหตุนี้ เราจึงขอแนะนําอย่างยิ่งให้คุณใช้ Room แทนการใช้ SQLite API โดยตรง

ตั้งค่า

หากต้องการใช้ Room ในแอป ให้เพิ่ม Dependency ต่อไปนี้ลงในไฟล์ build.gradle ของแอป

KotlinGroovy
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 เพื่อดึงข้อมูลจากฐานข้อมูลเป็นอินสแตนซ์ของออบเจ็กต์เอนทิตีข้อมูลที่เชื่อมโยง นอกจากนี้ แอปยังใช้เอนทิตีข้อมูลที่กําหนดเพื่ออัปเดตแถวจากตารางที่เกี่ยวข้อง หรือสร้างแถวใหม่สําหรับการแทรกได้ด้วย รูปที่ 1 แสดงความสัมพันธ์ระหว่างคอมโพเนนต์ต่างๆ ของ Room

รูปที่ 1 แผนภาพสถาปัตยกรรมคลังห้อง

ตัวอย่างการใช้งาน

ส่วนนี้จะแสดงตัวอย่างการใช้งานฐานข้อมูล Room ที่มีเอนทิตีข้อมูลเดียวและ DAO เดียว

เอนทิตีข้อมูล

โค้ดต่อไปนี้จะกำหนดเอนทิตีข้อมูล User อินสแตนซ์ User แต่ละรายการแสดงแถวในตาราง user ในฐานข้อมูลของแอป

KotlinJava
@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

KotlinJava
@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
KotlinJava
@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 และออบเจ็กต์ฐานข้อมูลแล้ว คุณจะใช้โค้ดต่อไปนี้เพื่อสร้างอินสแตนซ์ของฐานข้อมูลได้

KotlinJava
val db = Room.databaseBuilder(
            applicationContext,
            AppDatabase::class.java, "database-name"
        ).build()
AppDatabase db = Room.databaseBuilder(getApplicationContext(),
        AppDatabase.class, "database-name").build();

จากนั้นคุณจะใช้เมธอดนามธรรมจาก AppDatabase เพื่อรับอินสแตนซ์ของ DAO ได้ จากนั้น คุณจะใช้เมธอดจากอินสแตนซ์ DAO เพื่อโต้ตอบกับฐานข้อมูลได้ ดังนี้

KotlinJava
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 functional

Codelabs

บล็อก