在可能的项目中,我正在使用Android Architecture Components中的Paging库。从Room db读取数据,该数据库用作缓存,并且当到达列表的末尾时,我使用边界回调从网络api获取新数据。不幸的是,从api调用新的更新时,即使方法中带有布尔标志,它也会被调用4次或更多次,因此新数据不正确。
从数据库中我返回Datasource.Factory:
@Query("SELECT * FROM movieentity ORDER BY popularity DESC")
fun allMovies(): DataSource.Factory<Int, MovieEntity>
存储库中的方法,基本上我想清除缓存并从api引导下一页:
override fun allMovies(movieBoundaryCallback:
MainViewModel.MovieBoundaryCallback): LiveData<PagedList<Movie>> {
// Get data source factory from the local cache
val dataSourceFactory = moviesDao.allMovies().map {
MovieMapper.fromDb(
it
)
}
val config: PagedList.Config = PagedList.Config.Builder()
.setInitialLoadSizeHint(DATABASE_PAGE_SIZE)
.setPageSize(DATABASE_PAGE_SIZE)
.setPrefetchDistance(0)
.build()
// Get the paged list
return LivePagedListBuilder(dataSourceFactory, config)
.setBoundaryCallback(movieBoundaryCallback)
.build()
}
override suspend fun refreshMovies(page: Int) {
withContext(Dispatchers.IO) {
moviesDao.deleteAll()
moviesDao.insertAll(*fetchMovies(page).toTypedArray())
}
}
Boundary回调类在ViewModel中定义为innner类:
val callback = MovieBoundaryCallback()
// get movies saved in local db
val movies = getMoviesUseCase.allMovies(callback)
...
inner class MovieBoundaryCallback : PagedList.BoundaryCallback<Movie>() {
private var lastRequestedPage = 1
private var isRequestInProgress = false
private fun refreshMoviesList() {
if (isRequestInProgress) return
isRequestInProgress = true
if (isInternetAvailable(getApplication())) {
lastRequestedPage++
try {
viewModelScope.launch {
getMoviesUseCase.refreshMovies(lastRequestedPage)
}
isRequestInProgress = false
} catch (e: Exception) {
e.printStackTrace()
}
}
}
override fun onItemAtEndLoaded(itemAtEnd: Movie) {
refreshMoviesList()
}
}
对于RecyclerView的适配器,我扩展了PagedListAdapter。也许是因为协程造成的?请帮助我解决此问题或给予提示。 预先感谢。
答案 0 :(得分:0)
我不太确定,但是我想问题是由于deleteAll()insertAll()引起的。 Room数据库的优点之一是它们是反应性的,因此它们可以在修改数据时发布信息,这是一个非常酷的功能。
问题在于,有时它们过于反应。 Room DB始终使用deleteAll()insertAll(),因为DB在deleteAll()之后以及insertAll()之后发送数据。您将必须使您的WS适应分页数据库,才能仅检索所需的数据,并且如果现有实体中可能发生更改,则能够执行“ smart insertAll()” ... < / p>