标签: android-paging-3

Android Paging 3 - 滚动和加载新页面时出现闪烁、故障或位置跳跃

大家好,我使用 Android Jetpack Paging 库 3,我正在创建一个实现网络 + 数据库场景的新闻应用程序,我正在关注 google 的 Codelab https://codelabs.developers.google.com/codelabs/android-paging,我几乎就像在 Codelab 中一样,我几乎匹配了示例中显示的所有操作https://github.com/android/architecture-components-samples/tree/main/PagingWithNetworkSample

它几乎按其应有的方式工作......但我的后端响应是页面键控的,我的意思是响应带有新闻列表和下一页网址,远程中介获取数据,填充数据库,设置存储库,设置视图模型。 ..

问题是:当recyclerview加载数据时,会发生以下情况:recyclerview闪烁、项目跳转、被删除、再次添加等等。我不知道为什么 recyclerview 或其 itemanimator 的行为如此,看起来如此丑陋和故障。更重要的是,当我滚动到列表末尾时,会获取新项目,并且再次发生故障和跳跃效果。

如果您能帮助我,我将非常感激,我已经坐了三天了,提前非常感谢您。这是我的代码片段:

@Entity(tableName = "blogs")
data class Blog(
@PrimaryKey(autoGenerate = true)
val databaseid:Int,

@field:SerializedName("id")
val id: Int,
@field:SerializedName("title")
val title: String,

@field:SerializedName("image")
val image: String,

@field:SerializedName("date")
val date: String,

@field:SerializedName("share_link")
val shareLink: String,

@field:SerializedName("status")

val status: Int,

@field:SerializedName("url")
val url: String
) {
var categoryId: Int? = null
var tagId: Int? = null
 }
Run Code Online (Sandbox Code Playgroud)

这是 DAO

@Insert(onConflict …
Run Code Online (Sandbox Code Playgroud)

android android-architecture-components android-paging android-paging-library android-paging-3

23
推荐指数
1
解决办法
9172
查看次数

理解PagingSource的getRefreshKey

我从 Paging 2 迁移到 Paging 3 库,现在我使用它PagingSource从服务器加载数据页面。但我很难理解getRefreshKey必须在那里重写的方法。我找到了一些代码示例,如何根据用于获取后续页面的密钥来实现它,但我仍然不明白。基于这些示例,我编写了以下代码:

override fun getRefreshKey(state: PagingState<Pair<String, String>, User>): Pair<String, String>? {
    return state.anchorPosition?.let { anchorPosition ->
        state.closestPageToPosition(anchorPosition)?.prevKey
    }
}
Run Code Online (Sandbox Code Playgroud)

但如果我使它始终返回 null,它不会改变任何事情:

override fun getRefreshKey(state: PagingState<Pair<String, String>, User>): Pair<String, String>? = null
Run Code Online (Sandbox Code Playgroud)

那么我为什么不能选择最简单的解决方案呢?还是有我没有看到的用例?

android kotlin android-paging android-paging-3

20
推荐指数
2
解决办法
7568
查看次数

如何使用 jetpack 与 LazyVerticalGrid 组合分页

我正在尝试使用 LazyVerticalGrid 显示分页项目。我正在尝试的代码如下所示。

 val categories = repo.categories.collectAsLazyPagingItems()

 LazyVerticalGrid(
    cells = GridCells.Fixed(2),
    modifier = Modifier.padding(8.dp)
 ) {

      items(categories) { category ->
          Box(Modifier.padding(8.dp)) {
              CategoryView(category)
          }
      }

 }
Run Code Online (Sandbox Code Playgroud)

请注意,我已经导入了androidx.paging.compose.itemsandroidx.paging.compose.collectAsLazyPagingItems。也categories属于类型LazyPagingItems<Category>

LazyColumn它可以与和完美配合LazyRow,但不能LazyVerticalGrid。我收到的错误是:

Type mismatch.
Required:
Int
Found:
LazyPagingItems<Category>
Run Code Online (Sandbox Code Playgroud)

android android-jetpack-compose android-paging-3

18
推荐指数
4
解决办法
8283
查看次数

使用 StateFlow 和分页的 Android MVI 3

我正在尝试使用状态流和分页 3 来实现 android MVI 架构,但是当我有一个包含分页数据的视图状态时,我感到很困惑。

\n

问题是我将视图模型中的视图状态公开为状态流对象,但现在在该视图状态内我有另一个来自分页库的流对象。

\n

状态流中可以有一个流吗?如果它\xe2\x80\x99s 不是我应该做什么?

\n

这是我的代码,以供更多说明。

\n

任务库

\n
override fun list(\npageNumber: Int,\npageSize: Int,\ngroupId: Long?,\nquery: String\n): Flow<PagingData<Task>> {\nreturn Pager(\n    config = PagingConfig(\n        pageSize = Consts.PageSize,\n        maxSize = 200,\n        enablePlaceholders = false\n    ),\n    remoteMediator = TaskRemoteMediator(query, groupId, db, taskApi),\n    pagingSourceFactory = {\n        TaskDataSource(taskApi, groupId, query)\n    }\n).flow\n}\n
Run Code Online (Sandbox Code Playgroud)\n

任务视图模型

\n
viewModelScope.launch {\ntry {\n    _taskListViewState.emit(TaskListViewState.Loading)\n    val tasks = taskRepo.list(1, Consts.PageSize, intent.groupId, "")\n    _taskListViewState.emit(TaskListViewState.Data(tasks))\n} catch (e: Exception) {\n    _taskListViewState.emit(TaskListViewState.Error(R.string.unknown_error))\n}\n}\n
Run Code Online (Sandbox Code Playgroud)\n

任务列表视图状态

\n
sealed class TaskListViewState {\nobject Idle …
Run Code Online (Sandbox Code Playgroud)

android kotlin android-paging-3 kotlin-stateflow

18
推荐指数
1
解决办法
1704
查看次数

Paging 3 - PagingDataAdapter 完成刷新并且 DiffUtil 完成比较后如何滚动到 RecyclerView 顶部?

我将 Paging 3 与 RemoteMediator 结合使用,它在从网络获取新数据的同时显示缓存的数据。当我刷新我的PagingDataAdapter(通过调用refresh()它)时,我希望我的 RecyclerView 在刷新完成后滚动到顶部。在代码实验室loadStateFlow中,他们尝试通过以下方式处理这个问题:

lifecycleScope.launch {
    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 { binding.list.scrollToPosition(0) }
    }
Run Code Online (Sandbox Code Playgroud)

这确实会向上滚动,但在 DiffUtil 完成之前。这意味着如果顶部确实插入了新数据,RecyclerView将不会一直向上滚动。

我知道 RecyclerView 适配器有一个AdapterDataObserver回调,当 DiffUtil 完成比较时我们可以收到通知。但这会导致适配器的各种竞争条件和PREPEND加载APPEND状态,这也会导致 DiffUtil 运行(但这里我们不想滚动到顶部)。

一种可行的解决方案是传递PagingData.empty()PagingDataAdapter并重新运行相同的查询(仅调用refresh是行不通的,因为PagingData现在是空的并且没有任何内容可以刷新),但我更愿意保持旧数据可见,直到我知道刷新实际上成功了。

paging android android-paging android-paging-library android-paging-3

11
推荐指数
1
解决办法
8549
查看次数

使用 RxJava 时刷新分页 3 库

homeViewModel.pagingDataFlow.subscribe(expensesPagingData -> {
                expenseAdapter.submitData(getLifecycle(), expensesPagingData);    
            }, throwable -> Log.e(TAG, "onCreate: " + throwable.getMessage()));

// ViewModel

 private void init() {
        pagingDataFlow = homeRepository.init();
        CoroutineScope coroutineScope = ViewModelKt.getViewModelScope(this);
        PagingRx.cachedIn(pagingDataFlow, coroutineScope);

    }

// Repository 
    public  Flowable<PagingData<ExpensesModel>> init() {
            // Define Paging Source
            expensePagingSource = new ExpensePagingSource(feDataService);
            // Create new Pager
            Pager<Integer, ExpensesModel> pager = new Pager<Integer, ExpensesModel>(
                    
                    new PagingConfig(10,
                            10,
                            false, 
                            10, 
                            100),
                    () -> expensePagingSource); // set paging source
    
            // inti Flowable
            pagingDataFlow = PagingRx.getFlowable(pager);
            return pagingDataFlow;
        }


I have tried to …
Run Code Online (Sandbox Code Playgroud)

android android-recyclerview android-paging-library android-paging-3

11
推荐指数
3
解决办法
5015
查看次数

Android Paging 3 如何过滤、排序和搜索我的数据

我正在尝试实现我正在使用 Room 的分页,我花了很长时间才意识到这一切都为我完成了,但我需要做的是能够过滤搜索并对我的数据进行排序。我想暂时将其保留为 LiveData,以便稍后交换为 Flow。\n我使用此方法来过滤搜索和排序,并且效果非常好,

\n
    @SuppressLint("DefaultLocale")\n    private fun searchAndFilterPokemon(): LiveData<List<PokemonWithTypesAndSpecies>> {\n        return Transformations.switchMap(search) { search ->\n            val allPokemon = repository.searchPokemonWithTypesAndSpecies(search)\n            Transformations.switchMap(filters) { filters ->\n                val pokemon = when {\n                    filters.isNullOrEmpty() -> allPokemon\n                    else -> {\n                        Transformations.switchMap(allPokemon) { pokemonList ->\n                            val filteredList = pokemonList.filter { pokemon ->\n                                pokemon.matches = 0\n                                val filter = filterTypes(pokemon, filters)\n                                filter\n                            }\n                            maybeSortList(filters, filteredList)\n                        }\n                    }\n                }\n                pokemon\n            }\n        }\n    }\n
Run Code Online (Sandbox Code Playgroud)\n

这里有一些切换映射,第一个是响应搜索更新

\n
    var search: MutableLiveData<String> = getSearchState()\n
Run Code Online (Sandbox Code Playgroud)\n

第二个是响应过滤器更新

\n
    val filters: MutableLiveData<MutableSet<String>> …
Run Code Online (Sandbox Code Playgroud)

sorting android android-paging android-paging-3

10
推荐指数
1
解决办法
2万
查看次数

Android Paging 3 库:如何使用新参数更改列表?

我有一个显示搜索项目列表的搜索片段。如果用户输入某些内容,我会将该字符串作为新的查询参数传递给 url,并使用 paging 3 库获取新列表。

第一个解决方案是:

//viewModel
lateinit var postListUrl: String

    val postList: Flow<PagingData<Post>> = Pager(PagingConfig(pageSize = 20)) {
        PostPagingSource(postRepository, postListUrl)
    }.flow.cachedIn(viewModelScope)

//fragment
fun showPostList(url: String) {
        postListAdapter.submitData(lifecycle, PagingData.empty())
        viewModel.postListUrl = url
        viewLifecycleOwner.lifecycleScope.launch {
            viewModel.postList.collectLatest {
                postListAdapter.submitData(it)
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

通过此解决方案,通过更改 url ( showPostList(newUrl),列表保持不变。也许在 viewModel 中使用缓存列表。

另一种解决方案是:使用showPostList(initUrl)in onViewCreatedof 片段,然后通过更改参数使用 blow 方法:

//fragment
fun changePostList(url: String) {
        viewModel.postListUrl = url
        postListAdapter.refresh()
    }
Run Code Online (Sandbox Code Playgroud)

这项工作有效,但如果旧列表和新列表有共同的项目,新列表将显示在最后一个共同的可见项目上。例如,如果旧列表的第 5 个位置项与新列表的第 7 个位置项相同,则在列表更改以显示新列表后,它将从第 7 个位置开始,而不是第一个项目。

在这里找到了另一个解决方案:

//viewModel
val postListUrlFlow = MutableStateFlow("") …
Run Code Online (Sandbox Code Playgroud)

android android-paging kotlin-flow android-paging-3

10
推荐指数
1
解决办法
4191
查看次数

页脚未在 Paging 3 中显示

我正在关注 Paging 3 的 Codelab。

分页工作正常,但尝试添加页脚似乎不起作用。

LoadStateAdapter我的代码在使用方面与 Codelab 完全一样

class ListLoadStateAdapter(
    private val retry: () -> Unit,
) : LoadStateAdapter<ListLoadStateAdapter.ListLoadStateViewHolder>() {

    override fun onBindViewHolder(holder: ListLoadStateViewHolder, loadState: LoadState) {
        holder.bind(loadState)
    }

    override fun onCreateViewHolder(
        parent: ViewGroup,
        loadState: LoadState,
    ) = ListLoadStateViewHolder.create(parent, retry)

    class ListLoadStateViewHolder(
        private val binding: ComponentPagedListFooterBinding,
        retry: () -> Unit,
    ) : RecyclerView.ViewHolder(binding.root) {

        init {
            binding.buttonRetry.setOnClickListener { retry.invoke() }
        }

        fun bind(loadState: LoadState) {
            if (loadState is LoadState.Error) {
                binding.textViewPlaceholderError.text = loadState.error.localizedMessage
            }

            binding.progressBar.isVisible = loadState is …
Run Code Online (Sandbox Code Playgroud)

android android-paging-3

10
推荐指数
1
解决办法
3613
查看次数

Paging3如何删除撰写中的项目

我有一个lazyColumn要使用paging3,\n我来自网络的数据,需要使用列表计数来要求服务器获取下一个数据\n但现在我需要删除一些特殊项目,如何删除它\xef\xbc\x8ci已经使用PagingSource.invalidate 引用我的lazyColumn

\n

android-jetpack-compose android-paging-3

9
推荐指数
0
解决办法
723
查看次数