分页库中的回调已多次调用

时间:2019-10-06 16:21:53

标签: android kotlin coroutine android-paging

在可能的项目中,我正在使用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。也许是因为协程造成的?请帮助我解决此问题或给予提示。 预先感谢。

1 个答案:

答案 0 :(得分:0)

我不太确定,但是我想问题是由于deleteAll()insertAll()引起的。 Room数据库的优点之一是它们是反应性的,因此它们可以在修改数据时发布信息,这是一个非常酷的功能。

问题在于,有时它们过于反应。 Room DB始终使用deleteAll()insertAll(),因为DB在deleteAll()之后以及insertAll()之后发送数据。您将必须使您的WS适应分页数据库,才能仅检索所需的数据,并且如果现有实体中可能发生更改,则能够执行“ smart insertAll()” ... < / p>