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

最新文章

  1. Ext.NET MVC 配置问题总结
  2. struts2封装客户端数据到Action
  3. C# log4net 不输出日志
  4. ural 1153. Supercomputer
  5. golang的哪些坑爷事: package实践
  6. 【转载】cocos2d-x教程 Mac系统下搭建Lua的编码环境
  7. OpenGL中的深度、深度缓存、深度测试及保存成图片
  8. 74HC595的中文资料
  9. μCos-ii学习笔记2_任务管理
  10. 记一次服务器Tomcat优化经历
  11. centos6.5安装ganglia-gmond
  12. k8s中的api server的ca证书,可以和front proxy ca证书一样么?
  13. macbook air 2012 mid 安装 windows10 双系统遇到错误 no bootable device insert boot disk and press any key
  14. hihoCoder week13 最近公共祖先·一
  15. spring mvc 跨域问题。。。解决
  16. 题解 P2146 【[NOI2015]软件包管理器】
  17. Pycharm中不支持中文编码的解决方案。Pycharm中文报错。 Pycharm出现的部分快捷键无效及解决办法
  18. /proc 目录详细说明
  19. splash渲染网页
  20. Linux——用户管理简单学习笔记(一)

热门文章

  1. Swift 介绍
  2. Java线程--Semaphore使用
  3. 何为VRRP
  4. Redis 学习笔记(六)Redis 如何实现消息队列
  5. Node介绍
  6. 3.HTTP协议详解
  7. 关于spring data redis repository @RedisHash注解的对象上有DateTime属性字段的问题
  8. Solution -「SDOI 2018」「洛谷 P4606」战略游戏
  9. Solution -「POI 2014」「洛谷 P5904」HOT-Hotels 加强版
  10. CentOS 7 编译部署LAMP环境