如何在Room数据库框架中实现onUpgrade回调和自定义DatabaseErrorHandler功能?

2026-05-23 06:341阅读0评论SEO基础
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1056个文字,预计阅读时间需要5分钟。

在Android中,Room为SQLite提供了高效稳定的抽象层,简化了开发流程。RoomDatabase.java是初始化数据库的关键组件,通过它,我们可以轻松创建RoomDatabase实例。

  在 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.Callback public 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();


┆ 凉 ┆ 暖 ┆ 降 ┆ 等 ┆ 幸 ┆ 我 ┆ 我 ┆ 里 ┆ 将 ┆   ┆ 可 ┆ 有 ┆ 谦 ┆ 戮 ┆ 那 ┆   ┆ 大 ┆   ┆ 始 ┆ 然 ┆
┆ 薄 ┆ 一 ┆ 临 ┆ 你 ┆ 的 ┆ 还 ┆ 没 ┆   ┆ 来 ┆   ┆ 是 ┆ 来 ┆ 逊 ┆ 没 ┆ 些 ┆   ┆ 雁 ┆   ┆ 终 ┆ 而 ┆
┆   ┆ 暖 ┆   ┆ 如 ┆ 地 ┆ 站 ┆ 有 ┆   ┆ 也 ┆   ┆ 我 ┆   ┆ 的 ┆ 有 ┆ 精 ┆   ┆ 也 ┆   ┆ 没 ┆ 你 ┆
┆   ┆ 这 ┆   ┆ 试 ┆ 方 ┆ 在 ┆ 逃 ┆   ┆ 会 ┆   ┆ 在 ┆   ┆ 清 ┆ 来 ┆ 准 ┆   ┆ 没 ┆   ┆ 有 ┆ 没 ┆
┆   ┆ 生 ┆   ┆ 探 ┆   ┆ 最 ┆ 避 ┆   ┆ 在 ┆   ┆ 这 ┆   ┆ 晨 ┆   ┆ 的 ┆   ┆ 有 ┆   ┆ 来 ┆ 有 ┆
┆   ┆ 之 ┆   ┆ 般 ┆   ┆ 不 ┆   ┆   ┆ 这 ┆   ┆ 里 ┆   ┆ 没 ┆   ┆ 杀 ┆   ┆ 来 ┆   ┆   ┆ 来 ┆

本文共计1056个文字,预计阅读时间需要5分钟。

在Android中,Room为SQLite提供了高效稳定的抽象层,简化了开发流程。RoomDatabase.java是初始化数据库的关键组件,通过它,我们可以轻松创建RoomDatabase实例。

  在 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.Callback public 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();


┆ 凉 ┆ 暖 ┆ 降 ┆ 等 ┆ 幸 ┆ 我 ┆ 我 ┆ 里 ┆ 将 ┆   ┆ 可 ┆ 有 ┆ 谦 ┆ 戮 ┆ 那 ┆   ┆ 大 ┆   ┆ 始 ┆ 然 ┆
┆ 薄 ┆ 一 ┆ 临 ┆ 你 ┆ 的 ┆ 还 ┆ 没 ┆   ┆ 来 ┆   ┆ 是 ┆ 来 ┆ 逊 ┆ 没 ┆ 些 ┆   ┆ 雁 ┆   ┆ 终 ┆ 而 ┆
┆   ┆ 暖 ┆   ┆ 如 ┆ 地 ┆ 站 ┆ 有 ┆   ┆ 也 ┆   ┆ 我 ┆   ┆ 的 ┆ 有 ┆ 精 ┆   ┆ 也 ┆   ┆ 没 ┆ 你 ┆
┆   ┆ 这 ┆   ┆ 试 ┆ 方 ┆ 在 ┆ 逃 ┆   ┆ 会 ┆   ┆ 在 ┆   ┆ 清 ┆ 来 ┆ 准 ┆   ┆ 没 ┆   ┆ 有 ┆ 没 ┆
┆   ┆ 生 ┆   ┆ 探 ┆   ┆ 最 ┆ 避 ┆   ┆ 在 ┆   ┆ 这 ┆   ┆ 晨 ┆   ┆ 的 ┆   ┆ 有 ┆   ┆ 来 ┆ 有 ┆
┆   ┆ 之 ┆   ┆ 般 ┆   ┆ 不 ┆   ┆   ┆ 这 ┆   ┆ 里 ┆   ┆ 没 ┆   ┆ 杀 ┆   ┆ 来 ┆   ┆   ┆ 来 ┆