美文网首页Android Jetpack
Jetpack系列-Room使用和源码分析

Jetpack系列-Room使用和源码分析

作者: 木水Code | 来源:发表于2022-05-15 11:29 被阅读0次

    1 简介

    Room是Google官方在SQLite基础上封装的一款数据持久库,是Jetpack全家桶的一员,和Jetpack其他库有着可以高度搭配协调的天然优势。Room使用APT技术,大大简化了使用SQLite的代码量,只需使用注解配合少量代码即可实现高效的数据库操作。

    优点:

    • Google官方库,和Jetpack其他库(比如Lifecycle,LiveData)等有天然的融合搭配使用优势。
    • 在编译器可以对SQL语法进行检查。
    • 使用APT,简单地几个注解搭配少量代码即可使用,大量减少模板代码。
    • 查询代码自定义,可以实现更复杂的查询功能,也可以对SQL语句进行优化。
    • 简化数据库的迁移路径。

    不足:

    • 查询时必须手动写SQL语句,不提供默认的查询配置。
    • 效率比其他数据库框架(GreenDao等)并没有多少提高。
    • 数据库版本升级稍显复杂。

    Google官方文档:https://developer.android.com/jetpack/androidx/releases/room

    2 主要组件

    Room 包含三个主要组件:

    • DataBase:数据库类,用@Database标注,继承RoomDatabase,用于保存数据库并作为应用持久性数据底层连接的主要访问点。
    • Entity:数据实体,用@Entity标注,用于表示应用的数据库中的表。
    • Data Access Object:数据访问对象 (DAO),用@DAO标注,提供您的应用可用于查询、更新、插入和删除数据库中的数据的方法。

    在DataBase中获取DAO,然后在业务层使用DAO去进行数据的操作。

    3 单独使用Room

    在Module的build.gradle下添加APT支持。

    plugins {
        id 'com.android.application'
        id 'kotlin-android'
        id 'kotlin-kapt'
    }
    

    在Module的build.gradle下引入依赖。

    def room_version = "2.4.2"
    
    implementation "androidx.room:room-runtime:$room_version"
    kapt "androidx.room:room-compiler:$room_version"
    

    创建数据实体Book,包含bookId,name,author,price4个字段,由于bookId被设为主键,需要自增长,所以构造方法里不能有bookId。

    @Entity标注Book,就表示在数据库中创建了一个名为“Book”的表。

    @PrimaryKey设置该字段是主键,autoGenerate = true表示主键自增长,bookId会从1开始,每插入一条数据就会+1.

    @ColumnInfo设置该字段在数据库中的列名,name后的值就是在数据库中的列名。@ColumnInfo可选,不添加的话数据库列名和实体字段名一致。

    @Entity
    class Book(
        var name: String,
        @field:ColumnInfo(name = "author") var author: String,
        @field:ColumnInfo(name = "price") var price: Float
    ) {
        @PrimaryKey(autoGenerate = true)
        var bookId = 0
        
        
        override fun toString(): String {
            return "Book(name='$name', author='$author', price=$price, bookId=$bookId)"
        }
    }
    

    接着创建一个接口类DAO,在DAO中定义数据库操作方法。用@Dao来标注,然后定义接口方法操作数据库,用对应的注解标注,增删改查分别对应@Insert@Delete@Update@Query

    @Dao
    interface BookDao {
    
        @Insert
        fun insert(book: Book)
    
        @Delete
        fun delete(book: Book)
    
        @Update
        fun update(book: Book)
    
        //根据名字查数据
        @Query("select * from Book where name like:name")
        fun queryBookByName(name: String): MutableList<Book>
    
        //根据一组id查数据
        @Query("select * from Book where bookId in(:bookIds)")
        fun queryBookByIds(bookIds: Array<Int>): MutableList<Book>
    
        //查询所有数据
        @Query("select * from Book")
        fun queryAllBook(): MutableList<Book>
    
        //查询所有数据中的name和author
        @Query("select name,author from Book")
        fun queryBookWithPartFiled(): MutableList<Book2>
        
    }
    

    然后创建DataBase,继承RoomDatabase,用注解@Database标注,entities后的值表示数据库中的实体,也就是表,可以有多个,version是数据库版本,exportSchema表示是否支持导出,如果没有指定数据库导出路径,需要设置为false,不然会报错。数据库导出请看文档:https://developer.android.com/jetpack/androidx/releases/room#compiler-options

    DataBase中提供了一个方法获取DAO。

    @Database(entities = [Book::class], version = 1, exportSchema = false)
    abstract class AppDataBase : RoomDatabase() {
        abstract fun bookDao(): BookDao
    }
    

    最后在Activity初始化数据库并使用。数据库初始化方法是Room.databaseBuilder(Context context, Class<T> klass, String name),3个参数分别是上下文,DataBase类,数据库名称。

    class MainActivity : AppCompatActivity() {
        
        private val TAG = "---MS---"
        
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            
            //Room默认需要在子线程使用
            thread {
                val database =
                Room.databaseBuilder(applicationContext, AppDataBase::class.java, "MsDB")
                //                    .allowMainThreadQueries()//如果需要在主线程中使用,可以开启这行代码
                    .build()
                val dao = database.bookDao()
                
                //插入4条数据
                dao.insert(Book("三体", "刘慈欣", 55.6f))
                dao.insert(Book("黄金时代", "王小波", 32.9f))
                dao.insert(Book("生死疲劳", "莫言", 32.9f))
                dao.insert(Book("一句顶一万句", "刘震云", 32.9f))
                
                Log.d(TAG, "查询名字为三体发的数据: ${dao.queryBookByName("三体")}")
                Log.d(TAG, "查询id为1,3,4的数据: ${dao.queryBookByIds(arrayOf(1, 3, 4))}")
                Log.d(TAG, "查询所有数据: ${dao.queryAllBook()}")
                Log.d(TAG, "查询name和author: ${dao.queryBookWithPartFiled()}")
                
            }
        }
    }
    

    回到BookDao中可以看到,queryBookWithPartFiled方法查询的不是Book表中所有列,而是name和author这两列,返回的对象是Book2,不是Book。这是因为Room查询的时候,查询的列必须和返回的实体中所有字段对应,这也是Room的一个弊端之一。所以这里又定义了一个Book2,用来接收查询到的数据,Book2中只有两个字段name和author,并且不能用@Entity标注,不然Book2也变成了数据库中的一张表。

    class Book2(
        var name: String,
        @field:ColumnInfo(name = "author") var author: String,
    ) {
        override fun toString(): String {
            return "Book2(name='$name', author='$author')"
        }
    }
    

    4 数据库版本升级

    Room的数据库版本升级稍显麻烦,核心是Migration类。

    修改实体类,新增一个publishData字段。

    @Entity
    class Book(
        var name: String,
        @field:ColumnInfo(name = "author") var author: String,
        @field:ColumnInfo(name = "price") var price: Float,
        //新增字段
        @field:ColumnInfo(name = "data") var publishData: String
    ) {
        @PrimaryKey(autoGenerate = true)
        var bookId = 0
        
        
        override fun toString(): String {
            return "Book(name='$name', author='$author', price=$price, bookId=$bookId)"
        }
    }
    

    然后把version改为2。

    @Database(entities = [Book::class], version = 2, exportSchema = false)
    abstract class AppDataBase : RoomDatabase() {
        abstract fun bookDao(): BookDao
    }
    

    定义一个内部类,继承Migration,实现migrate方法,执行语句往表中添加列。

    /**
    * 从版本1升级到版本2
    */
    inner class Migration1To2 : Migration(1, 2) {
        override fun migrate(database: SupportSQLiteDatabase) {
            //执行sql语句,添加data列
            database.execSQL("alter table book add column data TEXT not null default '2020-05-01' ")
        }
    }
    

    最后在Room初始化的时候添加.addMigrations(Migration1To2())

    val database =
        Room.databaseBuilder(applicationContext, AppDataBase::class.java, "MsDB")
    //                    .allowMainThreadQueries()//如果需要在主线程中使用,可以开启这行代码
        //升级
        .addMigrations(Migration1To2())
                        .build()
    

    5 源码分析

    Room使用APT技术,提供了大量的注解。

    当用@Dao标注BookDao类,会在build/generated/source/kapt/debug/包名/下生成BookDao_impl.java。该类实现了BookDao中所有的接口方法,实现了具体的增删改查方法。

    package cn.zhangmushui.room;
    
    import android.database.Cursor;
    import androidx.room.EntityDeletionOrUpdateAdapter;
    import androidx.room.EntityInsertionAdapter;
    import androidx.room.RoomDatabase;
    import androidx.room.RoomSQLiteQuery;
    import androidx.room.util.CursorUtil;
    import androidx.room.util.DBUtil;
    import androidx.room.util.StringUtil;
    import androidx.sqlite.db.SupportSQLiteStatement;
    import java.lang.Class;
    import java.lang.Integer;
    import java.lang.Override;
    import java.lang.String;
    import java.lang.StringBuilder;
    import java.lang.SuppressWarnings;
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    
    @SuppressWarnings({"unchecked", "deprecation"})
    public final class BookDao_Impl implements BookDao {
        private final RoomDatabase __db;
        
        private final EntityInsertionAdapter<Book> __insertionAdapterOfBook;
        
        private final EntityDeletionOrUpdateAdapter<Book> __deletionAdapterOfBook;
        
        private final EntityDeletionOrUpdateAdapter<Book> __updateAdapterOfBook;
        
        public BookDao_Impl(RoomDatabase __db) {
            this.__db = __db;
            this.__insertionAdapterOfBook = new EntityInsertionAdapter<Book>(__db) {
                @Override
                public String createQuery() {
                    return "INSERT OR ABORT INTO `Book` (`name`,`author`,`price`,`data`,`bookId`) VALUES (?,?,?,?,nullif(?, 0))";
                }
                
                @Override
                public void bind(SupportSQLiteStatement stmt, Book value) {
                    if (value.getName() == null) {
                        stmt.bindNull(1);
                    } else {
                        stmt.bindString(1, value.getName());
                    }
                    if (value.getAuthor() == null) {
                        stmt.bindNull(2);
                    } else {
                        stmt.bindString(2, value.getAuthor());
                    }
                    stmt.bindDouble(3, value.getPrice());
                    if (value.getPublishData() == null) {
                        stmt.bindNull(4);
                    } else {
                        stmt.bindString(4, value.getPublishData());
                    }
                    stmt.bindLong(5, value.getBookId());
                }
            };
            this.__deletionAdapterOfBook = new EntityDeletionOrUpdateAdapter<Book>(__db) {
                @Override
                public String createQuery() {
                    return "DELETE FROM `Book` WHERE `bookId` = ?";
                }
                
                @Override
                public void bind(SupportSQLiteStatement stmt, Book value) {
                    stmt.bindLong(1, value.getBookId());
                }
            };
            this.__updateAdapterOfBook = new EntityDeletionOrUpdateAdapter<Book>(__db) {
                @Override
                public String createQuery() {
                    return "UPDATE OR ABORT `Book` SET `name` = ?,`author` = ?,`price` = ?,`data` = ?,`bookId` = ? WHERE `bookId` = ?";
                }
                
                @Override
                public void bind(SupportSQLiteStatement stmt, Book value) {
                    if (value.getName() == null) {
                        stmt.bindNull(1);
                    } else {
                        stmt.bindString(1, value.getName());
                    }
                    if (value.getAuthor() == null) {
                        stmt.bindNull(2);
                    } else {
                        stmt.bindString(2, value.getAuthor());
                    }
                    stmt.bindDouble(3, value.getPrice());
                    if (value.getPublishData() == null) {
                        stmt.bindNull(4);
                    } else {
                        stmt.bindString(4, value.getPublishData());
                    }
                    stmt.bindLong(5, value.getBookId());
                    stmt.bindLong(6, value.getBookId());
                }
            };
        }
        
        @Override
        public void insert(final Book book) {
            __db.assertNotSuspendingTransaction();
            __db.beginTransaction();
            try {
                __insertionAdapterOfBook.insert(book);
                __db.setTransactionSuccessful();
            } finally {
                __db.endTransaction();
            }
        }
        
        @Override
        public void delete(final Book book) {
            __db.assertNotSuspendingTransaction();
            __db.beginTransaction();
            try {
                __deletionAdapterOfBook.handle(book);
                __db.setTransactionSuccessful();
            } finally {
                __db.endTransaction();
            }
        }
        
        @Override
        public void update(final Book book) {
            __db.assertNotSuspendingTransaction();
            __db.beginTransaction();
            try {
                __updateAdapterOfBook.handle(book);
                __db.setTransactionSuccessful();
            } finally {
                __db.endTransaction();
            }
        }
        
        @Override
        public List<Book> queryBookByName(final String name) {
            final String _sql = "select * from Book where name like?";
            final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 1);
            int _argIndex = 1;
            if (name == null) {
                _statement.bindNull(_argIndex);
            } else {
                _statement.bindString(_argIndex, name);
            }
            __db.assertNotSuspendingTransaction();
            final Cursor _cursor = DBUtil.query(__db, _statement, false, null);
            try {
                final int _cursorIndexOfName = CursorUtil.getColumnIndexOrThrow(_cursor, "name");
                final int _cursorIndexOfAuthor = CursorUtil.getColumnIndexOrThrow(_cursor, "author");
                final int _cursorIndexOfPrice = CursorUtil.getColumnIndexOrThrow(_cursor, "price");
                final int _cursorIndexOfPublishData = CursorUtil.getColumnIndexOrThrow(_cursor, "data");
                final int _cursorIndexOfBookId = CursorUtil.getColumnIndexOrThrow(_cursor, "bookId");
                final List<Book> _result = new ArrayList<Book>(_cursor.getCount());
                while(_cursor.moveToNext()) {
                    final Book _item;
                    final String _tmpName;
                    if (_cursor.isNull(_cursorIndexOfName)) {
                        _tmpName = null;
                    } else {
                        _tmpName = _cursor.getString(_cursorIndexOfName);
                    }
                    final String _tmpAuthor;
                    if (_cursor.isNull(_cursorIndexOfAuthor)) {
                        _tmpAuthor = null;
                    } else {
                        _tmpAuthor = _cursor.getString(_cursorIndexOfAuthor);
                    }
                    final float _tmpPrice;
                    _tmpPrice = _cursor.getFloat(_cursorIndexOfPrice);
                    final String _tmpPublishData;
                    if (_cursor.isNull(_cursorIndexOfPublishData)) {
                        _tmpPublishData = null;
                    } else {
                        _tmpPublishData = _cursor.getString(_cursorIndexOfPublishData);
                    }
                    _item = new Book(_tmpName,_tmpAuthor,_tmpPrice,_tmpPublishData);
                    final int _tmpBookId;
                    _tmpBookId = _cursor.getInt(_cursorIndexOfBookId);
                    _item.setBookId(_tmpBookId);
                    _result.add(_item);
                }
                return _result;
            } finally {
                _cursor.close();
                _statement.release();
            }
        }
        
        @Override
        public List<Book> queryBookByIds(final Integer[] bookIds) {
            StringBuilder _stringBuilder = StringUtil.newStringBuilder();
            _stringBuilder.append("select * from Book where bookId in(");
            final int _inputSize = bookIds.length;
            StringUtil.appendPlaceholders(_stringBuilder, _inputSize);
            _stringBuilder.append(")");
            final String _sql = _stringBuilder.toString();
            final int _argCount = 0 + _inputSize;
            final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, _argCount);
            int _argIndex = 1;
            for (Integer _item : bookIds) {
                if (_item == null) {
                    _statement.bindNull(_argIndex);
                } else {
                    _statement.bindLong(_argIndex, _item);
                }
                _argIndex ++;
            }
            __db.assertNotSuspendingTransaction();
            final Cursor _cursor = DBUtil.query(__db, _statement, false, null);
            try {
                final int _cursorIndexOfName = CursorUtil.getColumnIndexOrThrow(_cursor, "name");
                final int _cursorIndexOfAuthor = CursorUtil.getColumnIndexOrThrow(_cursor, "author");
                final int _cursorIndexOfPrice = CursorUtil.getColumnIndexOrThrow(_cursor, "price");
                final int _cursorIndexOfPublishData = CursorUtil.getColumnIndexOrThrow(_cursor, "data");
                final int _cursorIndexOfBookId = CursorUtil.getColumnIndexOrThrow(_cursor, "bookId");
                final List<Book> _result = new ArrayList<Book>(_cursor.getCount());
                while(_cursor.moveToNext()) {
                    final Book _item_1;
                    final String _tmpName;
                    if (_cursor.isNull(_cursorIndexOfName)) {
                        _tmpName = null;
                    } else {
                        _tmpName = _cursor.getString(_cursorIndexOfName);
                    }
                    final String _tmpAuthor;
                    if (_cursor.isNull(_cursorIndexOfAuthor)) {
                        _tmpAuthor = null;
                    } else {
                        _tmpAuthor = _cursor.getString(_cursorIndexOfAuthor);
                    }
                    final float _tmpPrice;
                    _tmpPrice = _cursor.getFloat(_cursorIndexOfPrice);
                    final String _tmpPublishData;
                    if (_cursor.isNull(_cursorIndexOfPublishData)) {
                        _tmpPublishData = null;
                    } else {
                        _tmpPublishData = _cursor.getString(_cursorIndexOfPublishData);
                    }
                    _item_1 = new Book(_tmpName,_tmpAuthor,_tmpPrice,_tmpPublishData);
                    final int _tmpBookId;
                    _tmpBookId = _cursor.getInt(_cursorIndexOfBookId);
                    _item_1.setBookId(_tmpBookId);
                    _result.add(_item_1);
                }
                return _result;
            } finally {
                _cursor.close();
                _statement.release();
            }
        }
        
        @Override
        public List<Book> queryAllBook() {
            final String _sql = "select * from Book";
            final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 0);
            __db.assertNotSuspendingTransaction();
            final Cursor _cursor = DBUtil.query(__db, _statement, false, null);
            try {
                final int _cursorIndexOfName = CursorUtil.getColumnIndexOrThrow(_cursor, "name");
                final int _cursorIndexOfAuthor = CursorUtil.getColumnIndexOrThrow(_cursor, "author");
                final int _cursorIndexOfPrice = CursorUtil.getColumnIndexOrThrow(_cursor, "price");
                final int _cursorIndexOfPublishData = CursorUtil.getColumnIndexOrThrow(_cursor, "data");
                final int _cursorIndexOfBookId = CursorUtil.getColumnIndexOrThrow(_cursor, "bookId");
                final List<Book> _result = new ArrayList<Book>(_cursor.getCount());
                while(_cursor.moveToNext()) {
                    final Book _item;
                    final String _tmpName;
                    if (_cursor.isNull(_cursorIndexOfName)) {
                        _tmpName = null;
                    } else {
                        _tmpName = _cursor.getString(_cursorIndexOfName);
                    }
                    final String _tmpAuthor;
                    if (_cursor.isNull(_cursorIndexOfAuthor)) {
                        _tmpAuthor = null;
                    } else {
                        _tmpAuthor = _cursor.getString(_cursorIndexOfAuthor);
                    }
                    final float _tmpPrice;
                    _tmpPrice = _cursor.getFloat(_cursorIndexOfPrice);
                    final String _tmpPublishData;
                    if (_cursor.isNull(_cursorIndexOfPublishData)) {
                        _tmpPublishData = null;
                    } else {
                        _tmpPublishData = _cursor.getString(_cursorIndexOfPublishData);
                    }
                    _item = new Book(_tmpName,_tmpAuthor,_tmpPrice,_tmpPublishData);
                    final int _tmpBookId;
                    _tmpBookId = _cursor.getInt(_cursorIndexOfBookId);
                    _item.setBookId(_tmpBookId);
                    _result.add(_item);
                }
                return _result;
            } finally {
                _cursor.close();
                _statement.release();
            }
        }
        
        @Override
        public List<Book2> queryBookWithPartFiled() {
            final String _sql = "select name,author from Book";
            final RoomSQLiteQuery _statement = RoomSQLiteQuery.acquire(_sql, 0);
            __db.assertNotSuspendingTransaction();
            final Cursor _cursor = DBUtil.query(__db, _statement, false, null);
            try {
                final int _cursorIndexOfName = 0;
                final int _cursorIndexOfAuthor = 1;
                final List<Book2> _result = new ArrayList<Book2>(_cursor.getCount());
                while(_cursor.moveToNext()) {
                    final Book2 _item;
                    final String _tmpName;
                    if (_cursor.isNull(_cursorIndexOfName)) {
                        _tmpName = null;
                    } else {
                        _tmpName = _cursor.getString(_cursorIndexOfName);
                    }
                    final String _tmpAuthor;
                    if (_cursor.isNull(_cursorIndexOfAuthor)) {
                        _tmpAuthor = null;
                    } else {
                        _tmpAuthor = _cursor.getString(_cursorIndexOfAuthor);
                    }
                    _item = new Book2(_tmpName,_tmpAuthor);
                    _result.add(_item);
                }
                return _result;
            } finally {
                _cursor.close();
                _statement.release();
            }
        }
        
        public static List<Class<?>> getRequiredConverters() {
            return Collections.emptyList();
        }
    }
    

    当用@DataBase标注AppDataBase类,会在build/generated/source/kapt/debug/包名/下生成AppDataBase_impl.java。该类主要进行了表的创建工作。

    package cn.zhangmushui.room;
    
    import androidx.annotation.NonNull;
    import androidx.room.DatabaseConfiguration;
    import androidx.room.InvalidationTracker;
    import androidx.room.RoomOpenHelper;
    import androidx.room.RoomOpenHelper.Delegate;
    import androidx.room.RoomOpenHelper.ValidationResult;
    import androidx.room.migration.AutoMigrationSpec;
    import androidx.room.migration.Migration;
    import androidx.room.util.DBUtil;
    import androidx.room.util.TableInfo;
    import androidx.room.util.TableInfo.Column;
    import androidx.room.util.TableInfo.ForeignKey;
    import androidx.room.util.TableInfo.Index;
    import androidx.sqlite.db.SupportSQLiteDatabase;
    import androidx.sqlite.db.SupportSQLiteOpenHelper;
    import androidx.sqlite.db.SupportSQLiteOpenHelper.Callback;
    import androidx.sqlite.db.SupportSQLiteOpenHelper.Configuration;
    import java.lang.Class;
    import java.lang.Override;
    import java.lang.String;
    import java.lang.SuppressWarnings;
    import java.util.Arrays;
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    
    @SuppressWarnings({"unchecked", "deprecation"})
    public final class AppDataBase_Impl extends AppDataBase {
      private volatile BookDao _bookDao;
    
      @Override
      protected SupportSQLiteOpenHelper createOpenHelper(DatabaseConfiguration configuration) {
        final SupportSQLiteOpenHelper.Callback _openCallback = new RoomOpenHelper(configuration, new RoomOpenHelper.Delegate(2) {
          @Override
          public void createAllTables(SupportSQLiteDatabase _db) {
            _db.execSQL("CREATE TABLE IF NOT EXISTS `Book` (`name` TEXT NOT NULL, `author` TEXT NOT NULL, `price` REAL NOT NULL, `data` TEXT NOT NULL, `bookId` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)");
            _db.execSQL("CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)");
            _db.execSQL("INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '049deb639df8f34cc670d599e5105986')");
          }
    
          @Override
          public void dropAllTables(SupportSQLiteDatabase _db) {
            _db.execSQL("DROP TABLE IF EXISTS `Book`");
            if (mCallbacks != null) {
              for (int _i = 0, _size = mCallbacks.size(); _i < _size; _i++) {
                mCallbacks.get(_i).onDestructiveMigration(_db);
              }
            }
          }
    
          @Override
          protected void onCreate(SupportSQLiteDatabase _db) {
            if (mCallbacks != null) {
              for (int _i = 0, _size = mCallbacks.size(); _i < _size; _i++) {
                mCallbacks.get(_i).onCreate(_db);
              }
            }
          }
    
          @Override
          public void onOpen(SupportSQLiteDatabase _db) {
            mDatabase = _db;
            internalInitInvalidationTracker(_db);
            if (mCallbacks != null) {
              for (int _i = 0, _size = mCallbacks.size(); _i < _size; _i++) {
                mCallbacks.get(_i).onOpen(_db);
              }
            }
          }
    
          @Override
          public void onPreMigrate(SupportSQLiteDatabase _db) {
            DBUtil.dropFtsSyncTriggers(_db);
          }
    
          @Override
          public void onPostMigrate(SupportSQLiteDatabase _db) {
          }
    
          @Override
          protected RoomOpenHelper.ValidationResult onValidateSchema(SupportSQLiteDatabase _db) {
            final HashMap<String, TableInfo.Column> _columnsBook = new HashMap<String, TableInfo.Column>(5);
            _columnsBook.put("name", new TableInfo.Column("name", "TEXT", true, 0, null, TableInfo.CREATED_FROM_ENTITY));
            _columnsBook.put("author", new TableInfo.Column("author", "TEXT", true, 0, null, TableInfo.CREATED_FROM_ENTITY));
            _columnsBook.put("price", new TableInfo.Column("price", "REAL", true, 0, null, TableInfo.CREATED_FROM_ENTITY));
            _columnsBook.put("data", new TableInfo.Column("data", "TEXT", true, 0, null, TableInfo.CREATED_FROM_ENTITY));
            _columnsBook.put("bookId", new TableInfo.Column("bookId", "INTEGER", true, 1, null, TableInfo.CREATED_FROM_ENTITY));
            final HashSet<TableInfo.ForeignKey> _foreignKeysBook = new HashSet<TableInfo.ForeignKey>(0);
            final HashSet<TableInfo.Index> _indicesBook = new HashSet<TableInfo.Index>(0);
            final TableInfo _infoBook = new TableInfo("Book", _columnsBook, _foreignKeysBook, _indicesBook);
            final TableInfo _existingBook = TableInfo.read(_db, "Book");
            if (! _infoBook.equals(_existingBook)) {
              return new RoomOpenHelper.ValidationResult(false, "Book(cn.zhangmushui.room.Book).\n"
                      + " Expected:\n" + _infoBook + "\n"
                      + " Found:\n" + _existingBook);
            }
            return new RoomOpenHelper.ValidationResult(true, null);
          }
        }, "049deb639df8f34cc670d599e5105986", "4598151ad10511f4531db7d976d441f6");
        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, "Book");
      }
    
      @Override
      public void clearAllTables() {
        super.assertNotMainThread();
        final SupportSQLiteDatabase _db = super.getOpenHelper().getWritableDatabase();
        try {
          super.beginTransaction();
          _db.execSQL("DELETE FROM `Book`");
          super.setTransactionSuccessful();
        } finally {
          super.endTransaction();
          _db.query("PRAGMA wal_checkpoint(FULL)").close();
          if (!_db.inTransaction()) {
            _db.execSQL("VACUUM");
          }
        }
      }
    
      @Override
      protected Map<Class<?>, List<Class<?>>> getRequiredTypeConverters() {
        final HashMap<Class<?>, List<Class<?>>> _typeConvertersMap = new HashMap<Class<?>, List<Class<?>>>();
        _typeConvertersMap.put(BookDao.class, BookDao_Impl.getRequiredConverters());
        return _typeConvertersMap;
      }
    
      @Override
      public Set<Class<? extends AutoMigrationSpec>> getRequiredAutoMigrationSpecs() {
        final HashSet<Class<? extends AutoMigrationSpec>> _autoMigrationSpecsSet = new HashSet<Class<? extends AutoMigrationSpec>>();
        return _autoMigrationSpecsSet;
      }
    
      @Override
      public List<Migration> getAutoMigrations(
          @NonNull Map<Class<? extends AutoMigrationSpec>, AutoMigrationSpec> autoMigrationSpecsMap) {
        return Arrays.asList();
      }
    
      @Override
      public BookDao bookDao() {
        if (_bookDao != null) {
          return _bookDao;
        } else {
          synchronized(this) {
            if(_bookDao == null) {
              _bookDao = new BookDao_Impl(this);
            }
            return _bookDao;
          }
        }
      }
    }
    

    关注木水小站 (zhangmushui.cn)和微信公众号【木水Code】,及时获取更多最新技术干货。

    相关文章

      网友评论

        本文标题:Jetpack系列-Room使用和源码分析

        本文链接:https://www.haomeiwen.com/subject/pvnvurtx.html