Android Room的使用详解

Android Room 在 Java 中的详细使用指南,涵盖从依赖配置到实际代码实现的完整流程:


一、添加依赖项

build.gradle 文件中添加 Room 的依赖项(Java 配置):

kotlin 复制代码
gradle
深色版本
dependencies {
    def room_version = "2.6.1" // 使用最新稳定版本

    // Room 运行时库
    implementation "androidx.room:room-runtime:$room_version"
    // Java 注解处理器
    annotationProcessor "androidx.room:room-compiler:$room_version"

    // 可选:RxJava2 支持
    implementation "androidx.room:room-rxjava2:$room_version"
    // 可选:测试支持
    androidTestImplementation "androidx.room:room-testing:$room_version"
}

二、定义数据实体(Entity)

使用 @Entity 注解定义数据库表对应的 Java 类。字段默认映射为表的列,可自定义列名或添加索引。

示例(Java):

typescript 复制代码
java
深色版本
import androidx.room.*;

@Entity(tableName = "users",
        indices = {@Index(value = {"last_name", "address"}, unique = true)})
public class User {
    @PrimaryKey(autoGenerate = true)
    private int id;

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

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

    private int age;

    private String address;

    // 构造方法
    public User(String firstName, String lastName, int age, String address) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
        this.address = address;
    }

    // Getter 和 Setter 方法
    public int getId() { return id; }
    public void setId(int id) { this.id = id; }

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

    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }

    public String getAddress() { return address; }
    public void setAddress(String address) { this.address = address; }
}

关键注解说明:

  • @Entity(tableName = "users"): 定义表名。
  • @PrimaryKey(autoGenerate = true): 主键,并启用自增。
  • @ColumnInfo(name = "column_name"): 自定义列名(可选)。
  • @Index: 定义索引,提升查询性能。

三、定义数据访问对象(DAO)

DAO 是访问数据库的接口,通过注解声明 SQL 操作方法。

示例(Java):

java 复制代码
java
深色版本
import androidx.room.*;
import java.util.List;
import android.database.Cursor;

@Dao
public interface UserDao {
    @Query("SELECT * FROM users")
    List<User> getAllUsers();

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    void insertUser(User user);

    @Update
    int updateUser(User user);

    @Delete
    int deleteUser(User user);

    @Query("SELECT * FROM users WHERE last_name LIKE :lastName")
    List<User> searchByLastName(String lastName);
}

关键注解说明:

  • @Query("SQL_STATEMENT"): 执行自定义 SQL 查询。
  • @Insert@Update@Delete: 分别对应插入、更新、删除操作。
  • onConflict = OnConflictStrategy.REPLACE: 冲突解决策略(如主键冲突时替换数据)。

四、创建数据库类(RoomDatabase)

数据库类是 Room 的核心,负责管理数据库的创建和 DAO 的获取。

示例(Java):

scala 复制代码
java
深色版本
import android.content.Context;
import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase;

@Database(entities = {User.class}, version = 1, exportSchema = false)
public abstract class AppDatabase extends RoomDatabase {
    public abstract UserDao userDao();

    private static volatile AppDatabase INSTANCE;

    public static AppDatabase getDatabase(final Context context) {
        if (INSTANCE == null) {
            synchronized (AppDatabase.class) {
                if (INSTANCE == null) {
                    INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
                            AppDatabase.class, "app_database")
                            .build();
                }
            }
        }
        return INSTANCE;
    }
}

关键点说明:

  • @Database(entities = {User.class}, version = 1): 定义实体类和数据库版本号。
  • Room.databaseBuilder(...): 构建数据库实例。
  • 单例模式确保数据库全局唯一。

五、在 ViewModel 中使用 Room

结合 ViewModelLiveData 实现数据与 UI 的分离,并支持生命周期感知的数据更新。

示例(Java):

scala 复制代码
java
深色版本
import android.app.Application;
import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import java.util.List;

public class UserViewModel extends AndroidViewModel {
    private final UserDao userDao;
    private final LiveData<List<User>> allUsers;

    public UserViewModel(@NonNull Application application) {
        super(application);
        AppDatabase database = AppDatabase.getDatabase(application);
        userDao = database.userDao();
        allUsers = userDao.getAllUsers();
    }

    public LiveData<List<User>> getAllUsers() {
        return allUsers;
    }

    public void insertUser(User user) {
        new InsertUserAsyncTask(userDao).execute(user);
    }

    public void deleteUser(User user) {
        new DeleteUserAsyncTask(userDao).execute(user);
    }

    // 使用 AsyncTask 在后台线程执行数据库操作
    private static class InsertUserAsyncTask extends AsyncTask<User, Void, Void> {
        private final UserDao userDao;

        private InsertUserAsyncTask(UserDao userDao) {
            this.userDao = userDao;
        }

        @Override
        protected Void doInBackground(User... users) {
            userDao.insertUser(users[0]);
            return null;
        }
    }

    private static class DeleteUserAsyncTask extends AsyncTask<User, Void, Void> {
        private final UserDao userDao;

        private DeleteUserAsyncTask(UserDao userDao) {
            this.userDao = userDao;
        }

        @Override
        protected Void doInBackground(User... users) {
            userDao.deleteUser(users[0]);
            return null;
        }
    }
}

关键点说明:

  • ViewModel: 用于管理 UI 相关的数据,避免 Activity/Fragment 中的直接数据库操作。
  • AsyncTask: 在后台线程执行数据库操作(Room 不允许在主线程操作数据库)。
  • LiveData: 自动更新 UI 当数据变化时。

六、初始化和使用数据库

在应用中初始化数据库并调用 DAO 方法:

ini 复制代码
java
深色版本
// 获取数据库实例
AppDatabase db = AppDatabase.getDatabase(context);
UserDao userDao = db.userDao();

// 插入数据
User user = new User("John", "Doe", 30, "123 Main St");
userDao.insertUser(user);

// 查询数据
List<User> users = userDao.getAllUsers();
for (User u : users) {
    Log.d("User", u.getFirstName() + " " + u.getLastName());
}

七、数据库迁移(Migration)

当修改了实体类(如添加/删除字段)时,需要处理数据库迁移:

示例(Java):

scala 复制代码
java
深色版本
// 添加新字段 "email" 到 User 实体类
@Database(entities = {User.class}, version = 2)
public abstract class AppDatabase extends RoomDatabase {
    // ...其他代码不变
}

// 创建 Migration 对象
static final Migration MIGRATION_1_2 = new Migration(1, 2) {
    @Override
    public void migrate(SupportSQLiteDatabase database) {
        database.execSQL("ALTER TABLE users ADD COLUMN email TEXT");
    }
};

// 构建数据库时添加迁移策略
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
        AppDatabase.class, "app_database")
        .addMigration(MIGRATION_1_2)
        .build();

八、注意事项

  1. 主线程限制
    Room 不允许在主线程执行数据库操作(会抛出 IllegalStateException)。必须使用后台线程(如 AsyncTaskThreadExecutorService)。
  2. 响应式数据
    如果 DAO 方法返回 LiveDataFlow,Room 会自动在后台线程查询并通知 UI 更新。
  3. 版本控制
    修改数据库结构时必须更新 @Databaseversion,并提供迁移策略(Migration)。
  4. 数据清理
    使用 .fallbackToDestructiveMigration() 可强制删除旧数据库并重新创建(仅限开发环境)。

九、完整项目结构

less 复制代码
深色版本
app/
├── build.gradle
├── src/main/java/
│   ├── com.example.roomdemo/
│   │   ├── entity/
│   │   │   └── User.java          // 实体类
│   │   ├── dao/
│   │   │   └── UserDao.java       // DAO 接口
│   │   ├── database/
│   │   │   └── AppDatabase.java   // 数据库类
│   │   ├── viewmodel/
│   │   │   └── UserViewModel.java // ViewModel
│   │   └── MainActivity.java      // 主界面

通过以上步骤,你可以在 Java 项目中高效使用 Room 实现本地数据库操作。

相关推荐
CYRUS_STUDIO39 分钟前
使用 readelf 分析 so 文件:ELF 结构解析全攻略
android·linux·逆向
小强开学前2 小时前
WebView 静态页面秒加载方案要点
android·webview
游戏开发爱好者84 小时前
基于uni-app的iOS应用上架,从打包到分发的全流程
android·ios·小程序·https·uni-app·iphone·webview
深盾科技4 小时前
Android Keystore签名文件详解与安全防护
android·安全·gitee
安卓开发者4 小时前
Android Glide插件化开发实战:模块化加载与自定义扩展
android·glide
夏天的味道٥8 小时前
MySQL explain命令的作用
android·mysql·adb
鹏多多8 小时前
flutter-使用confetti制作炫酷纸屑爆炸粒子动画
android·前端·flutter
Kapaseker10 小时前
Compose 图片加载新姿势 — Coil 新手基础教程
android·kotlin