iT邦幫忙

2022 iThome 鐵人賽

DAY 24
0

Room 持續性資料庫透過 SQLite 提供抽象層,可讓資料庫順暢存取,同時充分發揮 SQLite 的效用。特別是,Room 具有下列優點:

  • SQL 查詢的編譯時間驗證。
  • 盡可能減少重複且容易出錯的樣板程式碼的便利註解。
  • 簡化資料庫遷移路徑。

基於以上考量,強烈建議您使用 Room 代替直接使用 SQLite API

一、環境配置

gradle.build(Module)

  • java

    dependencies {
        implementation "androidx.room:room-runtime:2.4.3"
        annotationProcessor "androidx.room:room-compiler:2.4.3"
    }
    
  • kotlin

    dependencies {
        implementation "androidx.room:room-runtime:2.4.3"
        kapt "androidx.room:room-compiler:2.4.3"
    }
    

二、簡單使用

步驟:

  1. 創建數據類 @Entity
  2. 創建操作接口 @Dao
  3. 創建資料庫 @Database(entities = "步驟1的數據類")
  4. 操作資料庫
  5. 觀察資料庫變化

@Entity 常用註解

註解 意思
@PrimaryKey 每個資料庫至少需設置一個主鍵字段(用以表示唯一值)。 @primaryKey(autoGenerate = true)表示在建立物件的時候可以不用管這個欄位,Room會幫我們自動設定。
@ColumnInfo 修飾字段作為資料庫中的行(column)

@Dao 常用註解

DAO是用來定義操作資料的行為, 其中最常見的操作就是CRUD(增刪改查),我們只要使用對應的註解就行。

註解 意思
C: @Insert 新增資料
R: @Query 查詢資料
U: @Update 更新資料
D: @Delete 刪除資料

注意! 所有DB操作請勿運行在UI thread,不然會噴exception。

1. 創建數據類 @Entity

@Entity
public class User {

    @PrimaryKey(autoGenerate = true)
    private int uid;

    @ColumnInfo(name = "first_name")
    private String firstName;

    @ColumnInfo(name = "last_name")
    private String lastName;

    @ColumnInfo(name = "age")
    private int age;
    
    public User(String firstName, String lastName, int age) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
    }
    
    
    // ----- 該數據類所有屬性的getter和setter方法 -----
    public int getAge() { return age; }

    public void setName(int name) { this.age = name; }

    public int getUid() { return uid; }

    public void setUid(int uid) { this.uid = uid; }

    public String getFirstName() { return firstName; }

    public void setFirstName(String firstName) { this.firstName = firstName; }

    public String getLastName() { return lastName; }

    public void setLastName(String lastName) { this.lastName = lastName; }
}

2. 創建操作接口 @Dao

該接口用於定義操作資料的方法。

@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);
}

3. 創建資料庫 @Database(entities = "步驟1的數據類")

@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
    private final static String DB_NAME = "db_name"; // 資料庫名稱
    private static volatile AppDatabase singleton;

    // 必寫 Room才有辦法當我們把Dao和Entity關聯起來。
    public abstract UserDao userDao();

    
    // 使用單俐, 用以確保該應用只有一個實例, 這裡實現單例的方法是DCL(Double Check Lock)
    // volatile和synchronized是用來保證線程安全和確保在不同線程也只有一個實例。
    private AppDatabase() {} // 記得把構造方法設為私有
    public static AppDatabase getInstance(Context context) {
        if (singleton==null) {
            synchronized (AppDatabase.class) {
                if(singleton==null) {
                    singleton = Room.databaseBuilder(context, AppDatabase.class, DB_NAME).build();
                }
            }
        }
        return singleton;
    }
}

4. 操作資料庫

完成前面步驟1~3, 就可以開始操作資料庫了

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        UserDao userDao = AppDatabase.getInstance(this).userDao();  // 取得User操作類
        new Thread( () -> {
            userDao.insertAll(new User("Gilbert", "Stemmler", 25)); // 添加用戶1
            userDao.insertAll(new User("Juliette", "Macdonald", 30)); // 添加用戶2
        }).start();
    }
}

5. 觀察資料庫變化

首先,需要先運行項目,然後開啟App Inspection,等待一下即可看到步驟4新增的數據。


上一篇
Day23 - SharedPreferences
下一篇
Day25 - VideoView+MediaController
系列文
Android 開發 30天 初學之路筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言