In my implementation of Android paging library 2.0, the OnItemAtEndLoaded() is called numerous times even when not scrolled to the bottom of the list. The call keep on going without stopping.
The Episodes received from the API call are ordered by publish date just like the EpisodeDao's getAllEpisodes() method.
Any help will be much appreciated.
class DetailsViewModel(
private val episodeBoundaryCallback: EpisodeBoundaryCallback,
private val episodeDao: EpisodeDao,
private val pagedListConfig: PagedList.Config
) : ViewModel() {
var episodes: LiveData<PagedList<Episode>>? = null
fun getEpisodes(podcastId: String) {
if (episodes != null
&& episodes!!.value != null
&& !episodes!!.value!!.isEmpty()
) {
return
}
episodeBoundaryCallback.param = podcastId
val dataSourceFactory = episodeDao.getAllEpisodes(podcastId)
val pagedListBuilder =
LivePagedListBuilder<Int, Episode>(dataSourceFactory, pagedListConfig)
pagedListBuilder.setInitialLoadKey(1)
pagedListBuilder.setBoundaryCallback(episodeBoundaryCallback)
episodes = pagedListBuilder.build()
}
}
class EpisodeBoundaryCallback(
private val podcastsApi: PodcastsApi,
private val skipToItDatabase: SkipToItDatabase
): PagedList.BoundaryCallback<Episode>() {
private val tag = this::class.simpleName
private val loadTypeRefresh = 0
private val loadTypeAppend = 1
lateinit var param: String
var startPage: Long? = null
val loading: MutableLiveData<Boolean> = MutableLiveData()
val loadError: MutableLiveData<Boolean> = MutableLiveData()
override fun onZeroItemsLoaded() {
Log.d("REFRESHING","REFRESHING")
AppExecutors.getInstance().diskIO().execute {
requestPage(loadTypeRefresh, startPage)
}
}
override fun onItemAtEndLoaded(itemAtEnd: Episode) {
Log.d(tag,"APPEND")
AppExecutors.getInstance().diskIO().execute {
requestPage(loadTypeAppend, itemAtEnd.publishDate)
}
}
override fun onItemAtFrontLoaded(itemAtFront: Episode) {
}
private fun requestPage(requestType: Int, loadKey: Long?) {
val episodeResultCall = podcastsApi.getEpisodes(param, loadKey)
val response = episodeResultCall.execute()
if (response.isSuccessful) {
Log.d(tag, "isSuccessful")
loading.postValue(false)
loadError.postValue(false)
val body: PodcastDetails = response.body()!!
onEpisodeFetchCallback(body, requestType)
} else {
Log.d(tag, "!isSuccessful")
loading.postValue(false)
loadError.postValue(true)
}
}
var lastEpisode: Episode? = null
private fun onEpisodeFetchCallback(
podcastDetails: PodcastDetails,
loadType: Int
) {
skipToItDatabase.beginTransaction()
try {
if (loadType == loadTypeRefresh) {
skipToItDatabase.episodeDao().deleteAllEpisodes()
}
val episodes = podcastDetails.episodes
for (i in episodes) {
i.podcastId = param
lastEpisode = i
}
skipToItDatabase.episodeDao().insertEpisodes(episodes)
skipToItDatabase.setTransactionSuccessful()
} finally {
skipToItDatabase.endTransaction()
}
}
}
@Dao
interface EpisodeDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertEpisodes(episodes: List<Episode>)
@Query("SELECT * FROM episodes WHERE podcast_id = :podcastId ORDER BY publish_date DESC")
fun getAllEpisodes(podcastId: String): DataSource.Factory<Int, Episode>
@Query("DELETE FROM episodes")
fun deleteAllEpisodes()
}
@Headers("X-ListenAPI-Key: ${BuildConfig.apiKey}")
@GET("podcasts/{podcast_id}?sort=recent_first")
fun getEpisodes(
@Path("podcast_id") podcastId: String,
@Query("next_episode_pub_date") nextEpisodePubDate: Long?
): Call<PodcastDetails>
return new PagedList.Config.Builder()
.setPageSize(10)
.setPrefetchDistance(5)
.setEnablePlaceholders(true)
.setInitialLoadSizeHint(30)
.setMaxSize(60)
.build();
Apparently this was an issue with my recycler view size in XML