标签: android-paging

具有自定义数据源偏移量的Android分页库在RecyclerView中

我正在制作一个待办事项列表应用程序,我想拥有一个精美的列表,其中任务按日期分组在标题下(类似于Splen-DO的内容)。我将Android Paging库(与RecyclerView一起)与Room(作为数据存储)一起使用。对于标题,我使用RecyclerView的视图类型,并将标题添加到列表中,我使用的是自定义数据源,该数据包包装了Room的数据源,而不是返回Task Object,它返回的对象可以是Task或标头。

它是这样的:

  • Paging Library要求我的数据源加载项目,它计算由标头引起的偏移量,从数据库加载数据,并将标头添加到“任务(和标头)”列表中并返回。
  • 分页库使用我的适配器创建ViewHolders和视图并显示结果

一切正常,直到我对数据库进行更改。物品无缘无故地在RecyclerView中移动,有些重复并且在RecyclerView的乞求中有一些空的占位符。到目前为止,我一直在尝试解决“乞讨时出现空的占位符”问题。

我已经检查了我的数据源,它返回正确的数据且没有偏移量。然后我检查了适配器。getItem()方法返回所有具有偏移量的项,并在开头返回一些空项。当我开始深入研究时,我发现它是由PagedStorage中的某些mLoadingNullCount引起的,我不知道它的用途,因为它没有文档。

屏幕截图

列表可正常
使用列表可正常
使用在我对列表进行更改之后,列表顶部的
空占位符空占位符
列表错误(gif)
错误列表

一些代码

请忽略一些变量和类名,我使用一些捷克语单词,以便它们不会与某些系统类混淆。
Ukol =任务

适配器: 数据源: 片段:UkolListAdapter.java
MyDatasource.java
UkolListFragment.java

笔记

如果您需要更多代码或解释,请发表评论,我会为您添加。

编辑

我发现了一个错误。从房间数据库中的数据源可能不会给你名单staritng,你要求的,但在那里就是了,在loadInitial()并为您提供的索引(其中返回列表开始)中int position的parametr onResult()。因此,我在上返回了错误的数据loadInitial()。因此,我添加了一些算法,用于计算实际返回的数据LoadInitial()。我没有解决问题。

java android android-recyclerview android-paging

6
推荐指数
1
解决办法
1931
查看次数

PagedList 和 RecyclerView 交互的性能能否提升?

在我的 Android 应用程序中,我在RecyclerView使用 Room 和 Paging 库中显示数据。

我的实现与AsyncPagedListDiffer 文档中的示例非常相似。

流程如下:

  1. 数据库中的数据被更改
  2. 相应的Observer将更改传递给Adapter

    myLiveData.observe(viewLifecycleOwner, Observer {
        myAdapter.submitList(it)
    })
    
    Run Code Online (Sandbox Code Playgroud)
  3. AsyncPagedListDiffer计算差异并相应地更新列表

我的问题是第 3 步的性能下降。

即使我只在列表顶部插入一个项目,不同的项目也必须检查所有项目(这非常低效,尤其是对于较大的数据集),而简单的notifyItemInserted(0)调用就足够了。

有没有办法解决这种行为?

例如,我可以告诉它不必检查所有项目吗?或者任何其他解决方案?

我真的很感激任何建议。

android kotlin android-livedata android-paging

6
推荐指数
0
解决办法
316
查看次数

带有 CoroutineScope 的边界回调(Android 分页库)

我试图实现Android Paging libraryViewModelKotlin Coroutines

我有一个ViewModel实现CoroutineScope. 这取决于Repository

class MovieListViewModel(
    private val movieRepository: MovieRepository
) : ViewModel(), CoroutineScope {

    private val job = Job()
    override val coroutineContext: CoroutineContext
        get() = job + Dispatchers.IO

    private lateinit var _movies: LiveData<PagedList<MovieBrief>>

    val movies: LiveData<PagedList<MovieBrief>>
        get() = _movies

    init {
        launch {
            _movies = LivePagedListBuilder(movieRepository.getMovies(), DATABASE_PER_PAGE)
                .setBoundaryCallback(movieRepository.movieBoundaryCallback)
                .build()
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

这是我的Repository. 我注入BoundaryCallbackKodeinDependecy注射器。

class MovieRepositoryImpl(
    private val movieDao: MovieDao, …
Run Code Online (Sandbox Code Playgroud)

android kotlin android-viewmodel kotlinx.coroutines android-paging

6
推荐指数
1
解决办法
930
查看次数

带有分页库的无限 RecyclerView 中的 AdMob 广告

我正在使用分页库从服务器获取数据,我想在每 10 个项目后显示广告。因此,当用户向下滚动并获取新项目并将其添加到 PagedList 时。我希望加载和添加新广告,RecyclerView就像 Instagram 在提要中显示广告一样。因此,如果用户滚动到 200 个项目,将逐渐显示 20 个广告!!。我已经阅读了几个教程,但我还没有想出一个简单的方法来做到这一点。

这是我的适配器。

class RequestsPagedAdapter(
        private val retryCallback: () -> Unit, private val from: From)
    : PagedListAdapter<RequestsQuery.Request, RecyclerView.ViewHolder>(POST_COMPARATOR) {
    private var networkState: NetworkState? = null

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        when (getItemViewType(position)) {
            R.layout.z_request_item -> (holder as RequestViewHolder).bind(getItem(position)!!, from)
            R.layout.network_state_item -> (holder as NetworkStateItemViewHolder).bindTo(networkState)
            R.layout.ad_admob_banner -> (holder as AdMobViewHolder)
        }
    }

    override fun onBindViewHolder(
            holder: RecyclerView.ViewHolder,
            position: Int,
            payloads: MutableList<Any>) {
        if (payloads.isNotEmpty()) {
            val …
Run Code Online (Sandbox Code Playgroud)

android admob android-recyclerview android-paging

6
推荐指数
1
解决办法
1576
查看次数

将协程与分页库一起使用时未分派数据

我想使用分页库,我正在使用协程从网络调用中获取数据。我已经验证从服务器正确检索了数据,但是当我从该方法调用回调时,我loadInitial在观察到的 LiveData 上一无所获。我已经尝试“模拟”服务器(以避免使用协程)并将结果传递给 Fragment。

当我使用协程时,我首先在大小为 0 的观察者上得到结果,然后当网络调用完成并使用回调时,我什么也没得到。问题似乎是我配置协程的方式。

用于协程的调度程序是否有问题?

这是 DataSource 的完整示例。使用的 CoroutineScope 是 ViewModel 提供的。

internal class CharactersDataSource(
    private val coroutineScope: CoroutineScope,
    private val characterRepository: CharacterRepository
) : PositionalDataSource<Character>() {


    override fun loadRange(params: LoadRangeParams, callback: LoadRangeCallback<Character>) {
       TODO()
    }

    override fun loadInitial(params: LoadInitialParams, callback: LoadInitialCallback<Character>) {
        coroutineScope.launch {
            val result = characterRepository.fetchCharacters(
                params.requestedStartPosition,
                params.requestedLoadSize
            )
            if (result is Output.Success) {
                val value = result.value
                // This next call should trigger data to be dispatched onto the LiveData
                callback.onResult(value.results, …
Run Code Online (Sandbox Code Playgroud)

android android-architecture-components android-paging

6
推荐指数
0
解决办法
332
查看次数

Android PageKeyedDataSource(分页库)回调错误处理(src中有TODO异常)

我想通过loadInitialloadafter 中的callback.onError(或 callback.onRetryableError)将错误异常传递给我的分页适配器,但总是收到崩溃。经过一些调试后,我在库源中找到了这个: 在此处输入图片说明

这实际上是我在崩溃跟踪中收到的信息。只是“待办事项”。依赖版本:

'androidx.paging:paging-runtime-ktx:2.1.1'

在生产中出现这种异常消息是否可以,或者我做错了什么?无论如何......问题:任何其他“内置”方式将加载错误传递给适配器?

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

6
推荐指数
0
解决办法
549
查看次数

使用 Paging3 库时更改请求并获取新的数据流

我在我的项目中使用了 Jetpack 的Paging 3库来处理数据分页。我有一个用例,当用户更改搜索请求中的某些内容(例如添加/删除一些过滤器)时,我必须调用 API 并根据新的搜索请求使用新数据重新填充我的列表。但是当我创建新Pager实例并将其传递给我的PagingDataAdapter适配器时,它会抛出:

java.lang.IllegalStateException: Collecting from multiple PagingData concurrently is an illegal operation.
Run Code Online (Sandbox Code Playgroud)

我的实现是这样的:


存储库

class Repository {
    fun getDataStream(request: Request): Flow<PagingData<Response>> {
        return Pager(
            config = PagingConfig(
                pageSize = 10,
                initialLoadSize = 10,
                prefetchDistance = 3
            ),
            initialKey = 1,
            pagingSourceFactory = {
                DataPagingSource(
                    request = request,
                    repository = this
                )
            }
        ).flow
    }

    fun getData(page: Int, request: Request): Result<Response> {
        return remoteDataSource.getData(page, request)
    }
}
Run Code Online (Sandbox Code Playgroud)

数据分页源

class DataPagingSource(
    private …
Run Code Online (Sandbox Code Playgroud)

android android-paging android-paging-library

6
推荐指数
2
解决办法
2515
查看次数

我们如何处理房间生成的分页代码的运行时错误?

这个示例项目中,我有一个 DAO,它在 FTS4 表上使用 Paging 2 来搜索它,使用用户提供的搜索表达式:

  @Query("SELECT snippet(paragraphsFts) FROM paragraphs JOIN paragraphsFts "+
      "ON paragraphs.id == paragraphsFts.rowid WHERE paragraphsFts.prose "+
      "MATCH :search ORDER BY sequence")
  abstract fun filtered(search: String): DataSource.Factory<Int, String>
Run Code Online (Sandbox Code Playgroud)

我有一个BookRepositoryfiltered()函数,它只是通过对 DAO 的调用,我有一个SearchViewModel将 the 转换DataSource.Factory为 a的函数LiveData

class SearchViewModel(search: String, repo: BookRepository) : ViewModel() {
  val paragraphs = repo.filtered(search).toLiveData(pageSize = 15)
}
Run Code Online (Sandbox Code Playgroud)

我有一个观察结果的片段

    vm.paragraphs.observe(this.viewLifecycleOwner) {
      adapter.submitList(it)
    }
Run Code Online (Sandbox Code Playgroud)

只要用户没有输入语法错误的搜索表达式,这就可以正常工作。在这种情况下,Room 会抛出异常,我看不到在哪里可以捕获它。

2020-08-30 …
Run Code Online (Sandbox Code Playgroud)

android android-room android-paging

6
推荐指数
0
解决办法
282
查看次数

如何在 Paging 3 库中检查列表大小或空列表

按照此处提供的说明,我已经能够成功实现新的 alpha07 版本的 Paging 3 库:https : //developer.android.com/topic/libraries/architecture/paging/v3-paged-data#g​​uava-livedata

但是,现在我需要检查返回的列表是否为空以便向用户显示视图或文本,但我无法在其分页设计的流结构中附加任何检查。

目前,这是我onViewCreated在遵循他们的指南后在 Java 中使用我的代码的方式:

        MyViewModel viewModel = new ViewModelProvider(this).get(MyViewModel.class);

        LifecycleOwner lifecycleOwner = getViewLifecycleOwner();
        Lifecycle lifecycle = lifecycleOwner.getLifecycle();
        Pager<Integer, MyEntity> pager = new Pager<>(new PagingConfig(10), () -> viewModel.getMyPagingSource());
        LiveData<PagingData<MyEntity>> pagingDataLiveData = PagingLiveData.cachedIn(PagingLiveData.getLiveData(pager), lifecycle);

        pagingDataLiveData.observe(lifecycleOwner, data -> adapter.submitData(lifecycle, data));
Run Code Online (Sandbox Code Playgroud)

我尝试.filter在我的datain上附加 a adapter.submitData(lifecycle, data),但null尽管列表为空,但它从未收到项目。

在这种情况下,如何检查提交给适配器的数据何时为空?我在他们的文档中找不到任何指针。

编辑:这是我找到的解决方案,在这里发布是因为所选的答案严格来说不是解决方案,也不是在 Java 中,而是引导我找到它的答案。

我有一个附加LoadStateListener我的转接器,监听时LoadTypeREFRESHLoadState的NotLoading,再检查是否adapter.getItemCount是0。

LoadType对于这种情况,可能采用不同的方法更合适,但到目前为止,刷新对我来说是有效的,所以我选择了那个。

示例:

// …
Run Code Online (Sandbox Code Playgroud)

android android-paging android-paging-library

6
推荐指数
1
解决办法
2217
查看次数

Android:LoadStateAdapter 不在 recyclerview gridlayout 中居中

我目前的问题是,LoadStateAdapter显示加载和错误状态的 my 不在 my 内居中recyclerview,它有一个 gridlayout 作为布局管理器。我在官方 android 开发者网站上没有找到任何关于此的信息,所以我在这里问:如何将我的LoadStateAdapter内部集中在我的 Recyclerview 中?

当前的

在此处输入图片说明

分段

@AndroidEntryPoint
class ShopFragment : Fragment(R.layout.fragment_shop), ShopAdapter.OnItemClickListener {
    private val shopViewModel: ShopViewModel by viewModels()
    private val shopBinding: FragmentShopBinding by viewBinding()
    @Inject lateinit var shopListAdapter: ShopAdapter

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        bindObjects()
    }

    private fun bindObjects() {
        shopBinding.adapter = shopListAdapter.withLoadStateFooter(ShopLoadAdapter(shopListAdapter::retry))
        shopListAdapter.clickHandler(this)
    }

    override fun onDestroyView() {
        requireView().findViewById<RecyclerView>(R.id.rv_shop).adapter = null
        super.onDestroyView()
    }
}
Run Code Online (Sandbox Code Playgroud)

适配器

@FragmentScoped
class ShopLoadAdapter(private val retry: () …
Run Code Online (Sandbox Code Playgroud)

android kotlin android-recyclerview android-paging android-paging-3

6
推荐指数
2
解决办法
678
查看次数