SQLDelight for Android - 从SQL语句中生成Kotlin代码 - 2
扩展
Android分页库
AndroidX Paging2
要在Android分页库中使用SQLDelight, 需要添加分页库的扩展构件.
dependencies {
implementation "com.squareup.sqldelight:android-paging-extensions:1.5.3"
}
要创建一个DataSource
, 写个检索语句来获取行数和接收offset和limit的检索.
countPlayers:
SELECT count(*) FROM hockeyPlayer;
players:
SELECT *
FROM hockeyPlayer
LIMIT :limit OFFSET :offset;
val dataSource = QueryDataSourceFactory(
queryProvider = playerQueries::players,
countQuery = playerQueries.countPlayers(),
transacter = playerQueries,
).create()
AndroidX Paging3
SQLDelight为AndroidX Paging3维护了扩展, 当前处理beta阶段. 引入SQLDelight Paging3扩展:
dependencies {
implementation "com.squareup.sqldelight:android-paging3-extensions:1.5.3"
}
SQLDelight为分页数据提供了2个方法 -- 偏移分页和键集分页.
偏移分页
偏移分页通过使用OFFSET
和LIMIT
子句达到分页效果. 创建执行偏移分页的PagingSource
同分页检索一样, 要求count检索.
countPlayers:
SELECT count(*) FROM hockeyPlayer;
players:
SELECT *
FROM hockeyPlayer
LIMIT :limit OFFSET :offset;
import com.squareup.sqldelight.android.paging3.QueryPagingSource
val pagingSource: PagingSource = QueryPagingSource(
countQuery = playerQueries.countPlayers(),
transacter = playerQueries,
dispatcher = Dispatchers.IO,
queryProvider = playerQueries::players,
)
默认情况下, 如果没有指定分发器的话, 检索在Dispatchers.IO
上面执行. 期待使用RxJava的Scheduler
执行检索的话, 应该使用Scheduler.asCoroutineDispatcher
扩展函数.
键集分页
偏移分布简单且易于维护. 不幸的是, 它在大型数据集上表现不佳. SQL语句中的OFFSET
子句真的直接丢掉SQL检索中已经执行的行. 由此, 随着OFFSET
数值增长, 执行检索消耗的时候也增长. 要克服这个缺陷, SQLDelight提供了"键集分页"的实现PagingSource
. 与检索完整的数据集和低效地丢弃首个OFFSET
元素相反的是, 键集分页通过使用唯一列来限制检索的边界. 这以更高的开发人员维护为代价, 达到了更好的性能.
PagingSource
所接收的queryProvider
回调有2个参数 -- beginInclusive
是非空唯一Key
, 而endExclusive
则是可空唯一Key?
. 分页检索的核心示例如下所示.
keyedQuery:
SELECT * FROM hockeyPlayer
WHERE id >= :beginInclusive AND (id < :endExclusive OR :endExclusive IS NULL)
ORDER BY id ASC;
键集分页中的检索必须如上拥有唯一的排序.
beginInclusive
和endExclusive
均是预计算的键, 这些键用作页边界. 预计算页边界的时候创建页大小. pageBoundariesProvider
回调接收anchor: Key?
和limit: Long?
2个参数. 预计算页边界的示例代码展示如下.
pageBoundaries:
SELECT id
FROM (
SELECT
id,
CASE
WHEN ((row_number() OVER(ORDER BY id ASC) - 0) % :limit) = 0 THEN 1
WHEN id = :anchor THEN 1
ELSE 0
END page_boundary;
FROM hockeyPlayer
ORDER BY id ASC
)
WHERE page_boundary = 1;
SQL检索的预计算页边界很可能需要SQLite窗口函数. 窗口函数自SQLite 3.25.0引入, 并由此默认直到Android 30才可用. 要使用键集分页, SQLDelight推荐要么设置minApi 30
要么捆绑自己的SQLite版本. Requery提供了SQLite的最新分发作为独立库.
AndroidX分页库通过PagingConfig.initialLoadSize
, 允许首页加载与后续加载的页大小不同. 该函数应该避免使用, 因为pageBoundariesProvider
回调只在首页加载时触发一次. PagingConifg.initialLoadSize
和PagingConfig.pageSize
匹配失败将导致意外的页边界产生.
PagingSource
并不支持跳跃.
要创建PagingSource
, 需要使用QueryPagingSource
工厂方法.
import com.squareup.sqldelight.android.paging3.QueryPagingSource
val keyedSource = QueryPagingSource(
transacter = playerQueries,
dispatcher = Dispatchers.IO,
pageBoundariesProvider = playerQueries::pageBoundaries,
queryProvider = playerQueries::keyedQuery,
)
默认情况下, 如果没有指定分发器的话, 检索在Dispatchers.IO
上面执行. 期待使用RxJava的Scheduler
执行检索的话, 应该使用Scheduler.asCoroutineDispatcher
扩展函数..
转载自:https://juejin.cn/post/7145701856533512199