Android Jetpack Components of Room 学习笔记

关于 Room,网上优秀的文章太多了。本文我只从自己的角度介绍 Room 使用,相信对你也够用了的。

Room Google 文档:https://developer.android.google.cn/topic/libraries/architecture/room

一、环境配置:

// room 配置
    implementation "android.arch.persistence.room:runtime:1.1.1"
    implementation "android.arch.persistence.room:rxjava2:1.1.1"
    annotationProcessor "android.arch.persistence.room:compiler:1.1.1"

如果是 androidx,则参考官网的配置。

二、Room 结构简介:

Room 组件的三个核心部分,分别是:

1、Entity 数据实体类,同时映射为数据库中的表结构。

2、Dao 数据库表的增删改查操作类。

3、Database SqLite 数据库对象获取和管理类。

三、Entity 注解简介:

Entity 是注解。使用 Entity 标记的类,将会被映射为数据库中的表。以话题赛事提醒需求为例说明:

@Entity(tableName = "topic_match_table",
        primaryKeys = {"topic_id", "match_id"},
        indices = {
                @Index(value = {"topic_id"}),
                @Index(value = {"topic_id", "match_id"})
        })
@Keep
public class MatchEntity implements Parcelable {

    public MatchEntity() {

    }

    @Ignore
    public MatchEntity(int matchId) {
        this.mMatchId = matchId;
    }

    @Ignore
    public MatchEntity(String topicId, int matchId, String teamA, String teamB, long timeStart) {
        this.mTopicId = topicId;
        this.mMatchId = matchId;
        this.mTeamA = teamA;
        this.mTeamB = teamB;
        this.mTimeStart = timeStart;
    }

    // 话题 id
    @ColumnInfo(name = "topic_id")
    @NonNull
    public String mTopicId;

    // 赛事 id
    @ColumnInfo(name = "match_id")
    @NonNull
    public int mMatchId;

    // 赛队 A
    @ColumnInfo(name = "team_a")
    public String mTeamA;

    // 赛队 B
    @ColumnInfo(name = "team_b")
    public String mTeamB;

    // 闹钟开始时间
    @ColumnInfo(name = "time_start")
    public long mTimeStart;

    @Ignore
    public PendingIntent mPendingIntent;

    // 参考 AlarmManager.RTC_WAKEUP
    // ELAPSED 开头的代表系统运行逝去的时间,RTC 开头的是世界时钟
    // 以WAKEUP结尾的类型能够唤醒设备
    // public static final int RTC_WAKEUP = 0;
    // public static final int RTC = 1;
    // public static final int ELAPSED_REALTIME_WAKEUP = 2;
    // public static final int ELAPSED_REALTIME = 3;
    // 闹钟类型
    @Ignore
    public int mAlarmManagerType = AlarmManager.RTC_WAKEUP;


    @Override
    public String toString() {
        String name = MatchEntity.class.getCanonicalName();
        if (name == null) {
            return super.toString();
        }

        String timeString = SimpleDateFormat.getDateTimeInstance().format(new Date(mTimeStart));
        return name + " -> mTopicId = " +
                mTopicId +
                " mMatchId = " +
                mMatchId +
                " mTeamA = " +
                mTeamA +
                " mTeamB = " +
                mTeamB +
                " mTimeStart = " +
                timeString;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(this.mTopicId);
        dest.writeInt(this.mMatchId);
        dest.writeString(this.mTeamA);
        dest.writeString(this.mTeamB);
        dest.writeLong(this.mTimeStart);
        dest.writeParcelable(this.mPendingIntent, flags);
        dest.writeInt(this.mAlarmManagerType);
    }

    protected MatchEntity(Parcel in) {
        this.mTopicId = in.readString();
        this.mMatchId = in.readInt();
        this.mTeamA = in.readString();
        this.mTeamB = in.readString();
        this.mTimeStart = in.readLong();
        this.mPendingIntent = in.readParcelable(PendingIntent.class.getClassLoader());
        this.mAlarmManagerType = in.readInt();
    }

    public static final Parcelable.Creator<MatchEntity> CREATOR = new Parcelable.Creator<MatchEntity>() {
        @Override
        public MatchEntity createFromParcel(Parcel source) {
            return new MatchEntity(source);
        }

        @Override
        public MatchEntity[] newArray(int size) {
            return new MatchEntity[size];
        }
    };
}

1、类声明处使用了 @Entity 注解。tableName 属性表示 MatchEntity 类映射到数据中的表名为 topic_match_table。primaryKeys 属性表示创建了一个联合主键。indices 属性值表明创建了 2 个索引。

扫描二维码关注公众号,回复: 12584910 查看本文章

2、属性和构造函数上使用了 @Ignore 注解。除了无参的构造函数外,其他所有的构造函数都需要添加此注解。不想被映射到数据库表字段的属性需要添加此注解。

3、在属性上使用了 @ColumnInfo 注解,表示此属性映射到数据库表的字段名。如果不添加此注解,则类属性名和表字段名相同。

4、设置为主键的属性,需要添加 @NonNull 注解。

5、也可以直接在某属性上使用 @PrimaryKey 注解声明主键。

以上只是 Entity 部分内容,掌握了这么多基本够用。

四、Dao 注解简介:

使用 Dao 注解标注的接口,承载着对 Entity 增删改查的使命。

@Dao
public interface MatchDao {

    @Query("SELECT match_id FROM topic_match_table WHERE topic_id = :topicId")
    int[] getTopicMatchesId(String topicId);

    @Query("SELECT * FROM topic_match_table")
    List<MatchEntity> getAllMatches();

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    void insertMatch(MatchEntity... matchEntities);

    @Delete
    void deleteMatch(MatchEntity... matchEntities);

    @Query("DELETE FROM topic_match_table WHERE topic_id = :topicId AND match_id = :matchId")
    void deleteMatchById(String topicId, int matchId);
}

1、@Dao 标注在接口上,忘记是否可以是抽象类了。

2、对数据库的增删改查四种操作,分别对应 @Insert / @Delete / @Update / @Query 4 个注解。

3、灵活运用。比喻删除操作也可以使用 @query 注解:@Query("DELETE FROM topic_match_table WHERE topic_id = :topicId AND match_id = :matchId")

4、@Insert 注解的 onConflict 参数含义是:当添加发生冲突时,直接替换旧数据。

5、更多信息可以参考 Room 组件注解的声明说明。

五、Database 注解简介:

Database 注解,标注配置一些数据库的信息。

@Database(entities = {MatchEntity.class}, version = MatchDatabase.DB_VERSION, exportSchema = false)
public abstract class MatchDatabase extends RoomDatabase {

    // you need update this version value when you update database structure
    public static final int DB_VERSION = 1;
    public static final String DB_NAME = "topic_match.db";

    public abstract MatchDao getMatchDao();

}

1、注意,自定义抽象类 MatchDatabase 继承RoomDatabase 类。

2、@Database 注解标注在 MatchDatabase 抽象类上,表示此数据库的名称、数据库中有哪些表、是否导出历史数据和表结构的 json 数据。

3、MatchDatabase 需要提供一个公共的抽象的方法,返回某 Entity 的操作类,比喻 MatchDao。

六、Room 使用简介:

public class MatchRoomHelper {

    private static MatchDatabase MATCH_DATABASE;
    private static MatchRoomHelper INSTANCE;

    private MatchRoomHelper(Context applicationContext) {
        MATCH_DATABASE = Room.databaseBuilder(applicationContext, MatchDatabase.class, MatchDatabase.DB_NAME)
                .allowMainThreadQueries() // 允许在主线程执行数据库操作
                .build();
    }

    public synchronized static MatchRoomHelper getInstance(Context applicationContext) {
        if (INSTANCE == null) {
            INSTANCE = new MatchRoomHelper(applicationContext);
        }
        return INSTANCE;
    }

    public List<MatchEntity> getAllMatches() {
        return MATCH_DATABASE.getMatchDao().getAllMatches();
    }

    public int[] getTopicMatchesId(String topicId) {
        return MATCH_DATABASE.getMatchDao().getTopicMatchesId(topicId);
    }

    public synchronized void insertMatch(MatchEntity... matchEntities) {
        MATCH_DATABASE.getMatchDao().insertMatch(matchEntities);
    }

    public synchronized void deleteMatch(MatchEntity... matchEntities) {
        MATCH_DATABASE.getMatchDao().deleteMatch(matchEntities);
    }

}

1、MatchDatabase 是实际的数据库配置承载类,可以使用 Room.databaseBuilder()创建数据库对象。参考 MatchRoomHelper 构造函数代码。

2、注意 allowMainThreadQueries() 配置,表示是否允许在主线程执行数据库操作。默认是不允许的,如果不允许,则在 UI 线程执行数据库操作会崩溃。

3、MatchDatabase 数据库对象不建议重复创建,或使用单例模式?!

4、通过 MatchRoomHelper 获取单例的 MatchDatabase 数据库对象,再获取 MatchDao 对象,就可以对对应的 Entity 进行增删改查操作了。

猜你喜欢

转载自blog.csdn.net/fesdgasdgasdg/article/details/100123799