Jetpack Room入门系列:(四)内部实现原理

在这里插入图片描述
Jetpack Room入门系列:(一)基本介绍
Jetpack Room入门系列:(二)使用DAO读写数据库
Jetpack Room入门系列:(三)实体/数据表关系
Jetpack Room入门系列:(四)内部实现原理
Jetpack Room入门系列:(五)数据库版本升级、数据迁移
Jetpack Room入门系列:(六)配合LiveData等三方库的使用


通过例子了解一下Room的底层实现原理。

Sample


Database

定义一个UserDatabase,只有一个实体User:

@Database(entities = [User::class], version = 1)
abstract class UserDatabase : RoomDatabase() {
    
    
 abstract fun userDao(): UserDao
}

Entity

User有三个字段(Column):

@Entity(tableName = USERS_TABLE)
data class User(
    @PrimaryKey val uid: Int,
    @ColumnInfo(name = FIRST_NAME_COLUMN) val firstName: String?,
    @ColumnInfo(name = LAST_NAME_COLUMN) val lastName: String?
)

UserDao

通过接口定义UserDao

@Dao
interface UserDao {
    
    
    @Query("SELECT * FROM $USERS_TABLE")
    fun getAll(): List<User>

    @Insert
    fun insertAll(vararg users: User)

    @Delete
    fun delete(user: User)
}

实现原理


Room在编译期通过kapt处理@Dao和@Database注解,并生成DAO和Database的实现类,UserDatabase_ImplUserDao_Impl。kapt生成的代码在 build/generated/source/kapt/

UserDatabase_Impl

public final class UserDatabase_Impl extends UserDatabase {
    
    
  private volatile UserDao _userDao;

  //RoomDataBase的init中调用
  @Override
  protected SupportSQLiteOpenHelper createOpenHelper(DatabaseConfiguration configuration) {
    
    
    final SupportSQLiteOpenHelper.Callback _openCallback = new RoomOpenHelper(configuration, new RoomOpenHelper.Delegate(1) {
    
    
      @Override
      public void createAllTables(SupportSQLiteDatabase _db) {
    
    
         //Implementation
      }


      @Override
      protected void onCreate(SupportSQLiteDatabase _db) {
    
    
         //Implementation
      }

    });
    
    final SupportSQLiteOpenHelper.Configuration _sqliteConfig = SupportSQLiteOpenHelper.Configuration.builder(configuration.context)
        .name(configuration.name)
        .callback(_openCallback)
        .build();
        
    final SupportSQLiteOpenHelper _helper = configuration.sqliteOpenHelperFactory.create(_sqliteConfig);
    
    return _helper;
  }

  @Override
  protected InvalidationTracker createInvalidationTracker() {
    
    
    final HashMap<String, String> _shadowTablesMap = new HashMap<String, String>(0);
    HashMap<String, Set<String>> _viewTables = new HashMap<String, Set<String>>(0);
    return new InvalidationTracker(this, _shadowTablesMap, _viewTables, "users");
  }

  @Override
  public void clearAllTables() {
    
    
    super.assertNotMainThread();
    final SupportSQLiteDatabase _db = super.getOpenHelper().getWritableDatabase();
    try {
    
    
      super.beginTransaction();
      _db.execSQL("DELETE FROM `users`");
      super.setTransactionSuccessful();
    } finally {
    
    
      super.endTransaction();
      _db.query("PRAGMA wal_checkpoint(FULL)").close();
      if (!_db.inTransaction()) {
    
    
        _db.execSQL("VACUUM");
      }
    }
  }

  @Override
  public UserDao userDao() {
    
    
    //实现见后文
}
  • createOpenHelperRoom.databaseBuilder().build()创建Database时,会调用实现类的createOpenHelper()创建SupportSQLiteOpenHelper,此Helper用来创建DB以及管理版本
  • createInvalidationTracker :创建跟踪器,确保table的记录修改时能通知到相关回调方
  • clearAllTables:清空table的实现
  • userDao:创建UserDao_Impl

UserDao_Impl

public final class UserDao_Impl implements UserDao {
    
    
  private final RoomDatabase __db;

  private final EntityInsertionAdapter<User> __insertionAdapterOfUser;

  private final EntityDeletionOrUpdateAdapter<User> __deletionAdapterOfUser;

  public UserDao_Impl(RoomDatabase __db) {
    
    
    this.__db = __db;
    this.__insertionAdapterOfUser = new EntityInsertionAdapter<User>(__db) {
    
    
      //Implementation
    };
    this.__deletionAdapterOfUser = new EntityDeletionOrUpdateAdapter<User>(__db) {
    
    
      //Implementation
    };
  }

  @Override
  public void insertAll(final User... users) {
    
    
    //Implementation
  }

  @Override
  public void delete(final User user) {
    
    
    //Implementation
  }

  @Override
  public List<User> getAll() {
    
    
    //Implementation
  }

  @Override
  public List<User> loadAllByIds(final int[] userIds) {
    
    
    //Implementation
  }

  @Override
  public User findByName(final String first, final String last) {
    
    
    //Implementation
  }
}

UserDao_Impl 主要有三个属性:

  • __db:RoomDatabase的实例
  • __insertionAdapterOfUserEntityInsertionAdapterd实例,用于数据insert。上例中,将在installAll()中调用
  • __deletionAdapterOfUserEntityDeletionOrUpdateAdapter实例,用于数据的update/delete。 上例中,在delete()中调用

RoomDatabase.Builder

Room通过Build模式创建Database实例

val userDatabase = Room.databaseBuilder(
    applicationContext,
    UserDatabase::class.java,
    "users-db"
).build()

Builder的好处时便于对Database进行配置

  • createFromAsset()/createFromFile() :从SD卡或者Asset的db文件创建RoomDatabase实例
  • addMigrations() :添加一个数据库迁移(migration),当进行数据版本升级时需要
  • allowMainThreadQueries() :允许在UI线程进行数据库查询,默认是不允许的
  • fallbackToDestructiveMigration() :如果找不到migration则重建数据库表(会造成数据丢失)

除上面以外,还有其他很多配置。调用build()后,创建UserDatabase_Impl,并调用init(),内部会调用createOpenHelper()

userDao()

@Override
public UserDao userDao() {
    
    
  if (_userDao != null) {
    
    
    return _userDao;
  } else {
    
    
    synchronized(this) {
    
    
      if(_userDao == null) {
    
    
        _userDao = new UserDao_Impl(this);
      }
      return _userDao;
    }
  } 
}

通过构造参数,向UserDao_Impl传入RoomDatabase

insertAll()

@Override
public void insertAll(final User... users) {
    
    
  __db.assertNotSuspendingTransaction();
  __db.beginTransaction();
  try {
    
    
    __insertionAdapterOfUser.insert(users);
    __db.setTransactionSuccessful();
  } finally {
    
    
    __db.endTransaction();
  }
}

使用__db开启事务,使用__insertionAdapterOfUser执行插入操作

delete()

@Override
public void delete(final User user) {
    
    
  __db.assertNotSuspendingTransaction();
  __db.beginTransaction();
  try {
    
    
    __deletionAdapterOfUser.handle(user);
    __db.setTransactionSuccessful();
  } finally {
    
    
    __db.endTransaction();
  }
}

同insertAll()

getAll()

@Override
public List<User> getAll() {
    
    
  final String _sql = "SELECT * FROM users";
  final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 0);
  __db.assertNotSuspendingTransaction();
  final Cursor _cursor = DBUtil.query(__db, _statement, false, null);
  try {
    
    
    final int _cursorIndexOfUid = CursorUtil.getColumnIndexOrThrow(_cursor, "uid");
    final int _cursorIndexOfFirstName = CursorUtil.getColumnIndexOrThrow(_cursor, "first_name");
    final int _cursorIndexOfLastName = CursorUtil.getColumnIndexOrThrow(_cursor, "last_name");
    final List<User> _result = new ArrayList<User>(_cursor.getCount());
    while(_cursor.moveToNext()) {
    
    
      final User _item;
      final int _tmpUid;
      _tmpUid = _cursor.getInt(_cursorIndexOfUid);
      final String _tmpFirstName;
      _tmpFirstName = _cursor.getString(_cursorIndexOfFirstName);
      final String _tmpLastName;
      _tmpLastName = _cursor.getString(_cursorIndexOfLastName);
      _item = new User(_tmpUid,_tmpFirstName,_tmpLastName);
      _result.add(_item);
    }
    return _result;
  } finally {
    
    
    _cursor.close();
    _statement.release();
  }
}

基于@Query注解的sql语句创建RoomSQLiteQuery,然后创建cursor进行后续操作

猜你喜欢

转载自blog.csdn.net/vitaviva/article/details/112727555
今日推荐