如何在Room框架下注册onUpgrade回调及自定义DatabaseErrorHandler

博客 动态
0 173
优雅殿下
优雅殿下 2022-03-15 23:56:40
悬赏:0 积分 收藏

如何在Room框架下注册onUpgrade回调及自定义DatabaseErrorHandler

??在 Android 中,Room 为 SQLite 提供了高效稳定的抽象层,简化开发流程。RoomDatabase.java 是初始化数据库的重要构建组件,通过它我们可以添加RoomDatabase#Callback监听,RoomDatabase#Callback提供了以下回调接口:

/** * Callback for {@link RoomDatabase}. */public abstract static class Callback {    /**     * Called when the database is created for the first time. This is called after all the     * tables are created.     *     * @param db The database.     */    public void onCreate(@NonNull SupportSQLiteDatabase db) {    }    /**     * Called when the database has been opened.     *     * @param db The database.     */    public void onOpen(@NonNull SupportSQLiteDatabase db) {    }    /**     * Called after the database was destructively migrated     *     * @param db The database.     */    public void onDestructiveMigration(@NonNull SupportSQLiteDatabase db){    }}

但是对于RoomDatabase#Callback提供的回调接口有时很难满足我们的开发需求,因为它没有将数据库打开过程的完整生命周期事件暴露出来。我们更需要的是SupportSQLiteOpenHelper#Callback开放的生命周期事件:

  • onConfigure 在数据库创建或打开之前回调,在这可以添加一些数据库能力,如打开 WAL 日志模式
  • onCreate 数据库首次创建时回调
  • onUpgrade 数据库版本低于请求版本时回调,进行升级处理
  • onDowngrade 类似于 onUpgrade,数据库版本高于请求版本时回调,进行降级处理
  • onOpen 数据库连接打开后回调
  • onCorruption 在数据库损坏时调用,默认删除db及相关日志文件

??Room框架中SupportSQLiteOpenHelper#Callback的实现类是RoomOpenHelper,幸运的是这个 callback 被注入到SupportSQLiteOpenHelper.Configuration中,并且 Room 允许我们使用SupportSQLiteOpenHelper.Configuration来提供自定义的SupportSQLiteOpenHelper。因此我们可以对FrameworkSQLiteOpenHelperRoomOpenHelper进行一层代理并开放出想要的生命周期回调。
值得一提的是Room框架下,FrameworkSQLiteOpenHelper使用SupportSQLiteOpenHelper#CallbackonCorruption方法来处理数据库损坏的情况,而其处理策略是删除db及其关联的日志文件。

OpenHelper(Context context, String name, final FrameworkSQLiteDatabase[] dbRef,        final Callback callback) {    super(context, name, null, callback.version,            new DatabaseErrorHandler() {                @Override                public void onCorruption(SQLiteDatabase dbObj) {                    callback.onCorruption(getWrappedDb(dbRef, dbObj));                }            });    mCallback = callback;    mDbRef = dbRef;}

很多时候这并不是我们想要的处理方式,通过代理RoomOpenHelper,替换掉onCorruption的默认实现方式,这样就实现了自定义 DatabaseErrorHandler

下面给出具体的代码示例展示如何进行代理:

// 自定义 SupportSQLiteOpenHelper.Factory public class DecoratedOpenHelperFactory implements SupportSQLiteOpenHelper.Factory {    @NonNull    private final SupportSQLiteOpenHelper.Factory delegate;    @Nullable    private final SupportSQLiteOpenHelper.Callback customListener;    public DecoratedOpenHelperFactory(@NonNull SupportSQLiteOpenHelper.Factory factory, @Nullable SupportSQLiteOpenHelper.Callback customListener) {        this.delegate = factory;        this.customListener = customListener;    }    @Override    public SupportSQLiteOpenHelper create(@NonNull SupportSQLiteOpenHelper.Configuration configuration) {        final SupportSQLiteOpenHelper.Configuration sqliteConfig = SupportSQLiteOpenHelper.Configuration.builder(configuration.context)                .name(configuration.name)                .callback(new DecoratedCallback(configuration.callback, customListener))                .build();        return delegate.create(sqliteConfig);    }}// 自定义 SupportSQLiteOpenHelper.Callbackpublic class DecoratedCallback extends SupportSQLiteOpenHelper.Callback {    @NonNull    private final SupportSQLiteOpenHelper.Callback delegate;    @Nullable    private final SupportSQLiteOpenHelper.Callback customListener;    public DecoratedCallback(@NonNull SupportSQLiteOpenHelper.Callback supportSqLiteOpenHelperCallback, @Nullable SupportSQLiteOpenHelper.Callback customListener) {        super(supportSqLiteOpenHelperCallback.version);        this.delegate = supportSqLiteOpenHelperCallback;        this.customListener = customListener;    }    @Override    public void onCreate(@Nullable SupportSQLiteDatabase db) {        delegate.onCreate(db);        Optional.ofNullable(customListener).ifPresent(customListener -> customListener.onCreate(db));    }    @Override    public void onUpgrade(SupportSQLiteDatabase db, int oldVersion, int newVersion) {        delegate.onUpgrade(db, oldVersion, newVersion);        Optional.ofNullable(customListener).ifPresent(customListener -> customListener.onUpgrade(db, oldVersion, newVersion));    }    @Override    public void onDowngrade(SupportSQLiteDatabase db, int oldVersion, int newVersion) {        delegate.onDowngrade(db, oldVersion, newVersion);        Optional.ofNullable(customListener).ifPresent(customListener -> customListener.onDowngrade(db, oldVersion, newVersion));    }    @Override    public void onOpen(SupportSQLiteDatabase db) {        delegate.onOpen(db);        Optional.ofNullable(customListener).ifPresent(customListener -> customListener.onOpen(db));    }    @Override    public void onCorruption(SupportSQLiteDatabase db) {        Optional.ofNullable(customListener).ifPresent(customListener -> customListener.onCorruption(db));    }}

最后,Room的构造使用如下:

Room.databaseBuilder(context, databaseName)    .openHelperFactory(new DecoratedOpenHelperFactory(        new FrameworkSQLiteOpenHelperFactory(), new SupportSQLiteOpenHelper.Callback() {            @Override            public void onCreate(SupportSQLiteDatabase db) {            }            @Override            public void onUpgrade(SupportSQLiteDatabase db, int oldVersion, int newVersion) {            }            // etc        }))    .build();
posted @ 2022-03-15 23:35 zxzhang 阅读(0) 评论(0) 编辑 收藏 举报
回帖
    优雅殿下

    优雅殿下 (王者 段位)

    2018 积分 (2)粉丝 (47)源码

    小小码农,大大世界

     

    温馨提示

    亦奇源码

    最新会员