[Room数据库为数据源时显示带有分页库的ProgressBar

问题描述 投票:0回答:1

我的数据库查询操作可能需要很长时间,因此我想在查询进行时显示一个ProgressBar。当用户更改排序选项时,这尤其成问题,因为它会显示旧列表一段时间,直到出现新列表并更新RecyclerView。我只是不知道在哪里捕获此类查询的“加载中”和“成功”状态。

这是我从数据库中获取PagedList的方法:

fun getGameList(): LiveData<PagedList<Game>> {

    // Builds a SimpleSQLiteQuery to be used with @RawQuery
    val query = buildGameListQuery()

    val dataSourceFactory: DataSource.Factory<Int, Game> = database.gameDao.getGameList(query)

    val data: LiveData<PagedList<Game>> = LivePagedListBuilder(dataSourceFactory, DATABASE_PAGE_SIZE)
        .build()

    return data
}

并且我通过观察来更新我的列表:

val games = Transformations.switchMap(gameRepository.sortOptions) {
    gameRepository.getGameList()
}

我需要自定义DataSource和DataSource.Factory吗?如果是这样,我什至不知道从哪里开始。我相信这将是PositionalDataSource,但我找不到在线上实现自定义示例的任何示例。

我也在RecyclerView适配器上尝试过adapter.registerAdapterDataObserver()。当显示新的列表数据时,这会触发各种回调,但是在加载开始和停止时我无法从这些回调中识别出来。

android android-room android-architecture-components android-paging android-paging-library
1个回答
0
投票

我最终能够通过观察games LiveData来解决此问题。但是,这并不完全简单。

这是我的DatabaseState类:

sealed class DatabaseState {

    object Success : DatabaseState()

    object LoadingSortChange: DatabaseState()

    object Loading: DatabaseState()
}

捕获加载状态很容易。每当用户更新排序选项时,我都会调用这样的方法:

fun updateSortOptions(newSortOptions: SortOptions) {
    _databaseState.value = DatabaseState.LoadingSortChange
    _sortOptions.value = newSortOptions
}

成功状态是一个棘手的状态。由于我的排序选项与RecyclerView包含在单独的Fragment中,因此games LiveData观察器在保存新的排序选项时会触发两次(一旦ListFragment恢复,则触发一次,然后在数据库查询完成后再触发一次)。所以我不得不这样考虑:

/**
 * The observer that triggers this method fires once under normal circumstances, but fires
 * twice if the sort options change. When sort options change, the "success" state doesn't occur
 * until the second firing. So in this case, DatabaseState transitions from LoadingSortChange to
 * Loading, and finally to Success.
 */
fun updateDatabaseState() {
    when (databaseState.value) {
        Database.LoadingSortChange -> gameRepository.updateDatabaseState(DatabaseState.Loading)
        DatabaseState.Loading -> gameRepository.updateDatabaseState(DatabaseState.Success)
    }
}

最后,我需要对BindingAdapter进行一些更改以消除一些剩余的问题:

@BindingAdapter("gameListData", "databaseState")
fun RecyclerView.bindListRecyclerView(gameList: PagedList<Game>?, databaseState: DatabaseState) {
    val adapter = adapter as GameGridAdapter

    /**
     * We need to null out the old list or else the old games will briefly appear on screen
     * after the ProgressBar disappears.
     */
    adapter.submitList(null)

    adapter.submitList(gameList) {
        // This Runnable moves the list back to the top when changing sort options
        if (databaseState == DatabaseState.Loading) {
            scrollToPosition(0)
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.