Skip to content
This repository was archived by the owner on Jan 10, 2025. It is now read-only.

Fix scroll to top behavior in PagingWithNetworkSample #881

Merged
merged 1 commit into from
Jul 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,32 +21,33 @@ import androidx.paging.PagingSource.LoadParams.Append
import androidx.paging.PagingSource.LoadParams.Prepend
import androidx.paging.PagingSource.LoadResult.Page
import com.android.example.paging.pagingwithnetwork.reddit.api.RedditApi
import com.android.example.paging.pagingwithnetwork.reddit.repository.inMemory.byItem.ItemKeyedSubredditPagingSource
import com.android.example.paging.pagingwithnetwork.reddit.vo.RedditPost
import retrofit2.HttpException
import java.io.IOException

/**
* A [PagingSource] that uses the before/after keys returned in page requests.
*
* @see [com.android.example.paging.pagingwithnetwork.reddit.repository.inMemory.byItem.ItemKeyedSubredditPagingSource]
* @see ItemKeyedSubredditPagingSource
*/
class PageKeyedSubredditPagingSource(
private val redditApi: RedditApi,
private val subredditName: String
private val redditApi: RedditApi,
private val subredditName: String
) : PagingSource<String, RedditPost>() {
override suspend fun load(params: LoadParams<String>): LoadResult<String, RedditPost> {
return try {
val data = redditApi.getTop(
subreddit = subredditName,
after = if (params is Append) params.key else null,
before = if (params is Prepend) params.key else null,
limit = params.loadSize
subreddit = subredditName,
after = if (params is Append) params.key else null,
before = if (params is Prepend) params.key else null,
limit = params.loadSize
).data

Page(
data = data.children.map { it.data },
prevKey = data.before,
nextKey = data.after
data = data.children.map { it.data },
prevKey = data.before,
nextKey = data.after
)
} catch (e: IOException) {
LoadResult.Error(e)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,18 @@ import androidx.lifecycle.AbstractSavedStateViewModelFactory
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.lifecycleScope
import androidx.paging.ExperimentalPagingApi
import androidx.paging.LoadState
import com.android.example.paging.pagingwithnetwork.GlideApp
import com.android.example.paging.pagingwithnetwork.R
import com.android.example.paging.pagingwithnetwork.reddit.ServiceLocator
import com.android.example.paging.pagingwithnetwork.reddit.repository.RedditPostRepository
import kotlinx.android.synthetic.main.activity_reddit.*
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.distinctUntilChangedBy
import kotlinx.coroutines.flow.filter

/**
* A list activity that shows reddit posts in the given sub-reddit.
Expand All @@ -55,14 +58,14 @@ class RedditActivity : AppCompatActivity() {
private val model: SubRedditViewModel by viewModels {
object : AbstractSavedStateViewModelFactory(this, null) {
override fun <T : ViewModel?> create(
key: String,
modelClass: Class<T>,
handle: SavedStateHandle
key: String,
modelClass: Class<T>,
handle: SavedStateHandle
): T {
val repoTypeParam = intent.getIntExtra(KEY_REPOSITORY_TYPE, 0)
val repoType = RedditPostRepository.Type.values()[repoTypeParam]
val repo = ServiceLocator.instance(this@RedditActivity)
.getRepository(repoType)
.getRepository(repoType)
@Suppress("UNCHECKED_CAST")
return SubRedditViewModel(repo, handle) as T
}
Expand All @@ -83,8 +86,8 @@ class RedditActivity : AppCompatActivity() {
val glide = GlideApp.with(this)
adapter = PostsAdapter(glide)
list.adapter = adapter.withLoadStateHeaderAndFooter(
header = PostsLoadStateAdapter(adapter),
footer = PostsLoadStateAdapter(adapter)
header = PostsLoadStateAdapter(adapter),
footer = PostsLoadStateAdapter(adapter)
)

lifecycleScope.launchWhenCreated {
Expand All @@ -102,10 +105,13 @@ class RedditActivity : AppCompatActivity() {
}

lifecycleScope.launchWhenCreated {
@OptIn(ExperimentalPagingApi::class, ExperimentalCoroutinesApi::class)
adapter.dataRefreshFlow.collectLatest {
list.scrollToPosition(0)
}
@OptIn(FlowPreview::class)
adapter.loadStateFlow
// Only emit when REFRESH LoadState for RemoteMediator changes.
.distinctUntilChangedBy { it.refresh }
// Only react to cases where Remote REFRESH completes i.e., NotLoading.
.filter { it.refresh is LoadState.NotLoading }
.collect { list.scrollToPosition(0) }
}
}

Expand Down