Android Room DataBase(一)

版权声明:本文为博主原创文章,未经博主允许,也可以随意转载。但麻烦,加个友情链接,增加点人气。 https://blog.csdn.net/l_o_s/article/details/79346426

前言:

众所周知,安卓原生的Sqlite数据库的操作不仅冗余麻烦,而且操作过程容易出问题。所以,后续github上出现了许多开源的封装了Sqlite的第三方library,来帮助你简化操作数据库,摆脱Sqlite的魔掌。比如,举世闻名的GreenDao。又比如,白痴化不需写Sql语句的Realm。又比如…. 。Anyway, 谷歌也注意到这个问题。所以,推出了Room DataBase,来解决这个问题。。。 希望,以后面试,不会再被要求手写创建、操作Sqlite的代码。

一、什么是Room数据库?

Room数据库是在Sqlite的基础上,进行了封装和优化。这让我们可以摆脱,繁琐的数据库操作,包括创建、更新数据库、表以及进行增删查改等。所以,谷歌极力推荐(we highly recommend using Room instead of SQLite),开发者使用Room代替Sqlite。不得不说的是,现在,很多的android面试试题,仍然要求面试者,手写创建、操作数据库的代码。私以为,这是愚蠢至极的做法。当然,仁者见仁, 智者见智。Personally, I can’t manage sqlite without baidu and google. Anyway, Let’s continue to discuss the Room DataBase. 另外,私以为,英文很重要。所以,后续的博客,都有部分会用英文来写。

Room数据库的结构图
Room

二、如何导入Room库(library)?

1、在Project的gradle里面,加入:

allprojects {
    repositories {
        google()
        jcenter()
    }
}

2、在module的gradle里面,加入:

  dependencies {
        // Room (use 1.1.0-alpha1 for latest alpha)
        implementation "android.arch.persistence.room:runtime:1.0.0"
        annotationProcessor "android.arch.persistence.room:compiler:1.0.0"

三、Room的三大组件。

Room的三大组件,换言之,即是Room由哪三个东西组成。

  • Entity:每一个Entity是一个类,同时也是一张表。默认情况下,类名即是表名,字段名,即是字段名。可以通过注解的形式,进行自定义表名和字段名,这个在下一篇会详细讲解。
  • Dao:每一个Dao,定义了一组对Entity的操作(Method, 即方法)。比如,增删查改。
  • DataBase:DataBase类似于Manager,通过DataBase,可以获取到任意有绑定到DataBase的Dao对象,再通过Dao对象,就可以对每一个Entity进行操作。作为一个DataBase类,必须满足以下三个条件:

    1、DataBase类必须是继承自RoomDataBase,并且其本身,必须是抽象类。
    2、通过在头部以注解的方式(后面会讨论如何做),添加一组Entity。这句话的意思是,只要Entity添加在DataBase类的头部,那该DataBase就可以,对已添加的Entity进行操作。
    3、至少包含一个不带参数的抽象方法,该方法返回一个已绑定的Entity所对应的Dao类型。

四、如何定义Entity?

以常见的User类来例子,我用代码向你解释一下,如何定义一个Entity类,代码如下:

@Entity
public class UserInfo {

    @PrimaryKey
    private int id;

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

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

    @Ignore
    private int sex; // I don't want to persist this field. So that added @Ignore annotation.

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

每一个Entity类,都会在其类名定义的前一行,增加一个注解@Entity,来标识该类是Room的一个Entity。每一个字段都有一个注解,这里就列举几个比较简单常见的:

1、@PrimaryKey,表示该字段是主键。
2、@ColumnInfo(name = “last_name”),表示该字段是表中的一个字段,字段名为自定义的last_name。
3、@Ignore,表示不对字段进行存储。

五、如何定义Dao?

如同解释,如何定义一个User的Entity一样。这里,我也用代码向你讲解,代码如下:

@Dao
public interface UserDao {

    @Query("select * from UserInfo")
    List<UserInfo> getAll();

    @Query("select * from UserInfo where id in (:userIds)")
    List<UserInfo> loadAllByIds(int[] userIds);

    @Query("select * from UserInfo where first_name like :first and "
            + "last_name like :last limit 1")
    UserInfo findByName(String first, String last);

    @Query("select id,first_name,last_name from UserInfo where id = :id")
    UserInfo getUserInfoViaId(int id);

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    long[]  insertAll(UserInfo... users);

    @Update
    void Update(UserInfo... users);

    @Delete
    void delete(UserInfo user);
}

每一个Dao类,都会在其类名定义的前一行,增加一个注解@Dao,来标识该类是Room的一个Dao。每一个方法,都有一个注解,用来表示,这个方法能对表进行的操作。这里,同样例举几个常见的注解:

1、@Query,表示查询数据。具体的sql语句写在其后的大括号里面,记得要加上” “双引号
2、@Insert,表示插入数据。(onConflict = OnConflictStrategy.REPLACE),这段表示,如果插入有冲突,就直接替换掉旧的数据。
3、@Update,表示更新数据。
4、@Delete,表示删除数据。

六、如何定义一个DataBase?

同样地,让我们直接看代码:

@Database(entities = {UserInfo.class}, version = 1)
public abstract class UserDataBase extends RoomDatabase {
    public abstract UserDao getUserDao();
}

每一个DataBase类,都会在其类名定义的前一行,增加一个注解@Database,来标识该类是Room的一个Database。其中,entities字段,表示该DataBase,绑定的表。多个表以逗号分开。version字段,表示该DataBase的版本。


到此为止,我们已经能够定义Room的三个主要组件,剩下的,就是向你展示,如何使用他们。同样的,直接看代码(需要注意的是,虽然Room允许在Main线程里面进行操作,但这是极不被推荐的。私以为,必须在子线程里进行操作,在Main线程更新UI。建议最好配合RxJava2,来使用Room)

// 通过Room的databaseBuilder,获取到UserDataBase的对象。
UserDataBase db = Room.databaseBuilder(getApplicationContext(),
        UserDataBase.class, "UserDataBase").build();

// 通过UserDataBase,获取UserDao对象。
UserDao userDao = db.getUserDao();

// 通过UserDao对象,对UserInfo表进行操作。

// 比如,通过用户id,来查询并获取一个UserInfo对象。
UserInfo userInfo = userDao.getUserInfoViaId(100);

// 打印, 用户信息。
if (userInfo == null) {
   Toast.makeText(MainActivity.this, "query failed!", Toast.LENGTH_SHORT).show();
 } else {
   Toast.makeText(MainActivity.this, "userName=" + userInfo.getFirstName()
    + userInfo.getLastName(),Toast.LENGTH_SHORT).show();}

到此为止,最基本的Room知识已经讲解完毕了。后续,我会再写一些进阶知识,比如如何封装、配合RxJava2使用Room等等。但在此之前,先同你展示一下,一个封装后的示例代码:

// 查询用户信息
private void queryUserInfo() {

        ThreadManager.execute(new SubscribeListener<UserInfo>() {

            @Override
            public UserInfo runOnSubThread() throws Exception {
                // Do something on subThread and then return the T bean.
                UserDao userDao = UserDataBase.getInstance(MainActivity.this).getUserDao();
                // query a user
                return userDao.getUserInfoViaId(100);
            }
        }, new ObserverListener<UserInfo>() {
            @Override
            public void runOnUiThread(@Nullable UserInfo userInfo) {
                // Do something on UiThread with UserInfo class.
                if (userInfo == null) {
                    Toast.makeText(MainActivity.this, "query failed!", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(MainActivity.this, "userName=" + userInfo.getFirstName() + userInfo.getLastName(),
                            Toast.LENGTH_SHORT).show();
                }
            }
        });

    }

好了,后续再见! Thank you for reading my posted, Happy New Chinese Year!

下篇详细讲解Entity的相关知识(传送门):http://blog.csdn.net/l_o_s/article/details/79348701
官方文档(传送门):https://developer.android.com/training/data-storage/room/index.html

猜你喜欢

转载自blog.csdn.net/l_o_s/article/details/79346426