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

Arm*_*186 5 android coroutine kotlin android-paging

在 May 项目中,我使用了 Android Architecture Components 中的 Paging 库。从用作缓存的 Room db 读取数据,当到达列表末尾时,我使用 Boundary 回调从网络 api 获取新数据。不幸的是,当从 api 调用新的更新时,它会被调用 4 次或更多次,即使方法中有布尔标志,因此新数据是不正确的。

从数据库我返回 Datasource.Factory:

    @Query("SELECT * FROM movieentity ORDER BY popularity DESC")
    fun allMovies(): DataSource.Factory<Int, MovieEntity>
Run Code Online (Sandbox Code Playgroud)

Repository中的方法,基本上我想从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())
        }
    }
Run Code Online (Sandbox Code Playgroud)

Boundary 回调类在 ViewModel 中定义为内部类:

    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()
        }
    }
Run Code Online (Sandbox Code Playgroud)

对于 RecyclerView 的适配器,我扩展了 PagedListAdapter。也许问题是因为协程?请帮我解决这个问题或给一个提示。提前致谢。

zap*_*tec 0

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

问题是,有时他们太反应了。deleteAll() insertAll() 始终是 Room DB 的问题,因为 DB 在 deleteAll() 之后以及 insertAll() 之后发送数据。您必须使您的 WS 适应分页数据库,以便能够仅检索所需的数据,并且在现有实体可能发生更改的情况下,能够执行“智能 insertAll()”...