Обратные вызовы в библиотеке пейджинга, вызываемые несколько раз - PullRequest
0 голосов
/ 06 октября 2019

В майском проекте я использую библиотеку подкачки из компонентов архитектуры Android. Данные считываются из Room db, которая используется в качестве кеша, и когда достигается конец списка, я получаю новые данные из сетевого API с помощью обратных вызовов Boundary. К сожалению, когда новые обновления вызываются из 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 как внутренний класс:

    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. Может быть проблема в сопрограммах? Пожалуйста, помогите мне решить эту проблему или дайте подсказку. Заранее спасибо.

...