Android-Jetpack笔记-Room

时间:2022-07-23
本文章向大家介绍Android-Jetpack笔记-Room,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

Room是一种ORM(对象关系映射)框架,可以用OOP(面向对象)的思路开发数据库,有点像早期的greenDAO,不过Room作为Jetpack的一员,能够返回更多类型的数据,比如能直接返回DataSource.Factory来友好的支持Paging的使用,本文主要总结基础的使用和原理。

Jetpack笔记代码

本文源码基于SDK 29

使用

引入依赖:

def room_version = "2.2.3"
implementation "androidx.room:room-runtime:$room_version"
//注解处理器,用于编译期根据注解来生成类
annotationProcessor "androidx.room:room-compiler:$room_version"

@Entity表示一个实体,即数据库中表的定义,

//声明一个实体User,表名为t_user
@Entity(tableName = "t_user")
class User {
    @PrimaryKey(autoGenerate = true)  //int型的自增主键
    @ColumnInfo(name = "id")          //表中字段的名字,不填则使用成员变量名
    private int mId;

    @Ignore                           //Ignore注解表示不进行数据库映射,只存在于内存中
    private boolean mSelected;
}

使用@Dao声明数据访问对象,即表的操作,

@Dao
interface UserDao {
    @Insert(onConflict = OnConflictStrategy.REPLACE)  //新增数据,发生冲突则替换
    void insertUsers(User... users);

    @Update(onConflict = OnConflictStrategy.REPLACE)  //更新数据,发生冲突则替换
    int updateUsers(User... users);

    @Delete
    void deleteUsers(User... users);  //删除数据

    @Query("SELECT * FROM t_user")    //查询数据
    List<User> queryUsers();
}

定义完表,还需要用@Database定义数据库,

//entities表示这个数据库都有哪些表,version表示数据库版本,用于数据库升级
@Database(entities = {User.class}, version = 1)
abstract class AppDatabase extends RoomDatabase {
    //提供dao对象给业务层使用
    public abstract UserDao userDao();
}

来到activity,进行使用

RoomActivity extends AppCompatActivity {
    void onCreate(Bundle savedInstanceState) {
        //创建数据库对象
        mAppDatabase = Room.databaseBuilder(this, AppDatabase.class, AppDatabase.DB_NAME)
                .allowMainThreadQueries()  //允许主线程操作数据库,不推荐
                .build();
        //获取dao对象
  mUserDao = mAppDatabase.userDao();
        //操作数据库
        mUserDao.insertUsers(user);
    }
}

原理

首先看看数据库的创建,进入AppDatabase类,点击查看他的实现类AppDatabase_Impl

//AppDatabase_Impl.java
SupportSQLiteOpenHelper createOpenHelper(DatabaseConfiguration configuration) {
    SupportSQLiteOpenHelper.Callback _openCallback = new RoomOpenHelper(configuration, new RoomOpenHelper.Delegate(1) {
        void createAllTables(SupportSQLiteDatabase _db) {
            //创建表
            _db.execSQL("CREATE TABLE IF NOT EXISTS `t_user` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT)");
        }
    };
}

@Override
public UserDao userDao() {
    if (_userDao != null) {
      return _userDao;
    } else {
      synchronized(this) {
        if(_userDao == null) {
          //创建dao对象
          _userDao = new UserDao_Impl(this);
        }
        return _userDao;
      }
    }
}

来到UserDao_Impl

//UserDao_Impl.java
UserDao_Impl(RoomDatabase __db) {
    this.__insertionAdapterOfUser = new EntityInsertionAdapter<User>(__db) {
        @Override
        public String createQuery() {
            //创建sql语句
            return "INSERT OR REPLACE INTO `t_user` (`id`,`name`) VALUES (nullif(?, 0),?)";
        }

        @Override
        public void bind(SupportSQLiteStatement stmt, User value) {
            //将参数绑定到sql语句的指定位置
            stmt.bindLong(1, value.getId());
            if (value.getName() == null) {
                stmt.bindNull(2);
            } else {
                stmt.bindString(2, value.getName());
            }
        }
    };
}

@Override
public void insertUsers(final User... users) {
    __insertionAdapterOfUser.insert(users);
}

insert会来到EntityInsertionAdapter

//EntityInsertionAdapter.java
void insert(T[] entities) {
    final SupportSQLiteStatement stmt = acquire();
    try {
        for (T entity : entities) {
            //根据前边实现的bind方法,绑定参数
            bind(stmt, entity);
            //执行stmt完成数据库操作
            stmt.executeInsert();
        }
    } finally {
        release(stmt);
    }
}

//省略调用链:acquire - getStmt - createNewStatement
SupportSQLiteStatement createNewStatement() {
    //获取前边创建的sql语句
    String query = createQuery();
    //最终去到SQLiteDatabase.compileStatement()里创建SQLiteStatement
    return mDatabase.compileStatement(query);
}

优缺点

  • 优点:
    • 使用简单,能友好的支持Paging(后续介绍)
  • 缺点:
    • 生成的类会增大包体积,当然值不值得就得看ROI了。

性能方面的问题暂不做分析。

参考文章

  • 简书-Android Room 框架学习