app: de-duplicate paging sources

Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
This commit is contained in:
Harsh Shandilya
2021-04-13 02:17:22 +05:30
parent 8e67be7a35
commit 654eb39877
3 changed files with 29 additions and 46 deletions
@@ -1,33 +0,0 @@
package dev.msfjarvis.lobsters.data.remote
import androidx.paging.PagingSource
import androidx.paging.PagingState
import dev.msfjarvis.lobsters.data.repo.LobstersRepository
import dev.msfjarvis.lobsters.model.LobstersPost
class HottestPostsPagingSource(
private val lobstersRepository: LobstersRepository,
) : PagingSource<Int, LobstersPost>() {
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, LobstersPost> {
return try {
val page = params.key ?: 1
// Update cache before fetching a list.
// This is done to make sure that we can update the isSaved status of incoming posts.
lobstersRepository.updateCache()
val posts = lobstersRepository.fetchHottestPosts(page)
LoadResult.Page(
data = posts,
prevKey = if (page == 1) null else page - 1,
nextKey = page.plus(1)
)
} catch (e: Exception) {
LoadResult.Error(e)
}
}
override fun getRefreshKey(state: PagingState<Int, LobstersPost>): Int {
return state.pages.size + 1
}
}
@@ -2,20 +2,16 @@ package dev.msfjarvis.lobsters.data.remote
import androidx.paging.PagingSource
import androidx.paging.PagingState
import dev.msfjarvis.lobsters.data.repo.LobstersRepository
import dev.msfjarvis.lobsters.model.LobstersPost
class NewestPostsPagingSource(
private val lobstersRepository: LobstersRepository,
class LobstersPagingSource(
private val getMorePosts: suspend (Int) -> List<LobstersPost>,
) : PagingSource<Int, LobstersPost>() {
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, LobstersPost> {
return try {
val page = params.key ?: 1
// Update cache before fetching a list.
// This is done to make sure that we can update the isSaved status of incoming posts.
lobstersRepository.updateCache()
val posts = lobstersRepository.fetchNewestPosts(page)
val posts = getMorePosts(page)
LoadResult.Page(
data = posts,
@@ -8,9 +8,9 @@ import androidx.paging.cachedIn
import dagger.hilt.android.lifecycle.HiltViewModel
import dev.msfjarvis.lobsters.data.local.SavedPost
import dev.msfjarvis.lobsters.data.preferences.ClawPreferences
import dev.msfjarvis.lobsters.data.remote.HottestPostsPagingSource
import dev.msfjarvis.lobsters.data.remote.NewestPostsPagingSource
import dev.msfjarvis.lobsters.data.remote.LobstersPagingSource
import dev.msfjarvis.lobsters.data.repo.LobstersRepository
import dev.msfjarvis.lobsters.model.LobstersPost
import dev.msfjarvis.lobsters.model.LobstersPostDetails
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
@@ -31,18 +31,18 @@ constructor(
val savedPosts = _savedPosts.asStateFlow()
val hottestPosts =
Pager(PagingConfig(25)) {
HottestPostsPagingSource(lobstersRepository).also { hottestPostsPagingSource = it }
LobstersPagingSource(getPostFetcher(hottest = true)).also { hottestPostsPagingSource = it }
}
.flow
.cachedIn(viewModelScope)
val newestPosts =
Pager(PagingConfig(25)) {
NewestPostsPagingSource(lobstersRepository).also { newestPostsPagingSource = it }
LobstersPagingSource(getPostFetcher(newest = true)).also { hottestPostsPagingSource = it }
}
.flow
.cachedIn(viewModelScope)
private var hottestPostsPagingSource: HottestPostsPagingSource? = null
private var newestPostsPagingSource: NewestPostsPagingSource? = null
private var hottestPostsPagingSource: LobstersPagingSource? = null
private var newestPostsPagingSource: LobstersPagingSource? = null
init {
lobstersRepository
@@ -86,6 +86,26 @@ constructor(
return lobstersRepository.isPostSaved(postId)
}
/**
* Returns a lambda that can be used to fetch the next round of hottest or newest posts. Having a
* single paging source makes it significantly easier to make changes to the logic both here and
* in [LobstersPagingSource].
*/
private fun getPostFetcher(
newest: Boolean = false,
hottest: Boolean = false,
): suspend (page: Int) -> List<LobstersPost> {
check(newest != hottest) { "Must pick one of newest or hottest" }
return { page ->
lobstersRepository.updateCache()
if (newest) {
lobstersRepository.fetchNewestPosts(page)
} else {
lobstersRepository.fetchHottestPosts(page)
}
}
}
private fun savePost(post: SavedPost) {
viewModelScope.launch {
lobstersRepository.addPost(post)