SqlBrite是对 Android 系统的 SQLiteOpenHelper 和 ContentResolver 的轻量级 Rx 封装,用来在 RxJava 中使用。
如何使用
创建一个 SqlBrite 对象,该对象是该库的入口:
SqlBritesqlBrite = SqlBrite.create();
需要注意的是,为了方便调试查询语句和结果,在创建 SqlBrite 的时候,可以指定一个 Logger 实现用来打印 log 信息。然后通过 BriteDatabase 或者 BriteContentResolver 的 setLoggingEnabled 函数来启用或者关闭 log 。
然后提供一个 SQLiteOpenHelper 实例和一个 Scheduler 实例来创建一个 BriteDatabase 对象:
BriteDatabasedb = sqlBrite.wrapDatabaseHelper(openHelper, Schedulers.io());
如果是使用 ContentProvider 的话,需要使用 ContentResolver 来创建一个 BriteContentResolver 对象:
BriteContentResolvercr = sqlBrite.wrapContentProvider(contentResolver, Schedulers.io());
Scheduler 是指定执行查询的操作的线程,由于查询数据库是不建议在 UI 线程中执行的,所以一般指定 Schedulers.io() 。
然后就需要使用 BriteDatabase 或者 BriteContentResolver 对象来查询、更新、删除数据了。
比如 BriteDatabase.createQuery 函数和 SQLiteDatabase.rawQuery 功能类似,参数有点不一样。返回一个 Observable 对象,并执行需要的查询语句。
Observable<Query> users = db.createQuery("users", "SELECT * FROM users");
users.subscribe(new Action1<Query>() {
@Override public void call(Queryquery) {
Cursorcursor = query.run();
// TODO parse data...
}
});
和 SQLiteDatabase.rawQuery 不同的是,这里需要指定所操作的数据库表名字, sqlbrite 使用这个表的名字来通知其他监听该表数据的 Observable 对象来更新数据。这就要求你只能通过 BriteDatabase 来访问数据库, 而不能使用 SQLiteOpenHelper 。
下面演示了数据变化通知功能:
final AtomicIntegerqueries = new AtomicInteger();
users.subscribe(new Action1<Query>() {
@Override public void call(Queryquery) {
queries.getAndIncrement();
}
});
System.out.println("Queries: " + queries.get()); // Prints 1
db.insert("users", createUser("jw", "Jake Wharton"));
db.insert("users", createUser("mattp", "Matt Precious"));
db.insert("users", createUser("strong", "Alec Strong"));
System.out.println("Queries: " + queries.get()); // Prints 4
当操作一个表的时候,所有订阅到该表的订阅者都可以收到数据变化的通知并返回新的数据。
如果不想接受数据更新了,则可以调用 Subscription 的 unsubscribe 函数来取消订阅:
final AtomicIntegerqueries = new AtomicInteger();
Subscription s = users.subscribe(new Action1<Query>() {
@Override public void call(Queryquery) {
queries.getAndIncrement();
}
});
System.out.println("Queries: " + queries.get()); // Prints 1
db.insert("users", createUser("jw", "Jake Wharton"));
db.insert("users", createUser("mattp", "Matt Precious"));
s.unsubscribe();
db.insert("users", createUser("strong", "Alec Strong"));
System.out.println("Queries: " + queries.get()); // Prints 3
如果提交大量数据,则可以使用事务处理:
final AtomicIntegerqueries = new AtomicInteger();
users.subscribe(new Action1<Query>() {
@Override public void call(Queryquery) {
queries.getAndIncrement();
}
});
System.out.println("Queries: " + queries.get()); // Prints 1
Transactiontransaction = db.newTransaction();
try {
db.insert("users", createUser("jw", "Jake Wharton"));
db.insert("users", createUser("mattp", "Matt Precious"));
db.insert("users", createUser("strong", "Alec Strong"));
transaction.markSuccessful();
} finally {
transaction.end();
}
System.out.println("Queries: " + queries.get()); // Prints 2
还可以在 Transaction 对象上用 try-with-resources
由于查询只是普通的 RxJava Observable 对象,所以可以在上面使用各种操作函数:
users.debounce(500, MILLISECONDS).subscribe(new Action1<Query>() {
@Override public void call(Queryquery) {
// TODO...
}
});
设计理念
SqlBrite 仅仅是一个用来协调更新数据和通知数据变化的轻量级封装,当你对数据表进行操作的时候,其他订阅者可以在数据发生变化的时候收到通知。然后可以用 RxJava 的方式来操作数据。
SqlBrite 不是一个 ORM 框架,也不是一个类型安全的查询框架。也不会提供数据库迁移的功能。所以 SqlBrite 的代码很简单,只有六个类几百行代码。