繁体   English   中英

如何使用交错网格回收器视图使用 MVVM 对 firestore 中的数据进行分页

[英]How to paginate data from firestore with MVVM using staggered grid recycler view

我想对 Firestore 中的数据进行分页,滚动时使用 RecyclerView 我想在看到所有项目时获取新文档

这是我的实现:在我的实现中发生的事情是,当我切换到包含回收器视图的片段时,它会以块的形式加载数据,限制为 10、10、10 ......但即使我不滚动也是一次它,它一次加载所有块。

迪->

@Module
@InstallIn(SingletonComponent::class)
object AppModule {
@Provides
@Singleton
fun provideQueryByName() = FirebaseFirestore.getInstance()
    .collectionGroup(Constants.POSTS_COLLECTION).whereEqualTo("doc_id", 
   "jetpack")
    .orderBy(Constants.POSTS_ORDER_BY, 
    Query.Direction.DESCENDING).limit(Constants.PAGE_SIZE.toLong())
}

分页源->

  class FirestorePagingSource (
  private val queryProductsByName: Query
           ) : PagingSource<QuerySnapshot, PostsModel>() {
  override fun getRefreshKey(state: PagingState<QuerySnapshot, 
  PostsModel>): QuerySnapshot? {
  return null
        }

override suspend fun load(params: LoadParams<QuerySnapshot>): LoadResult<QuerySnapshot, PostsModel> {
    return try {
        val currentPage = params.key ?: queryProductsByName.get().await()
        Log.e("data",currentPage.size().toString())
        val lastVisibleProduct = currentPage.documents[currentPage.size() - 1]
        val nextPage = queryProductsByName.startAfter(lastVisibleProduct).get().await()
        LoadResult.Page(
            data = currentPage.toObjects(PostsModel::class.java),
            prevKey = null,
            nextKey = nextPage
        )

    } catch (e: Exception) {
        LoadResult.Error(e)
    }

 }
}

适配器->

class PostsAdapter : PagingDataAdapter<PostsModel, PostsAdapter.PostsViewHolder>(Companion) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PostsViewHolder {
    val layoutInflater = LayoutInflater.from(parent.context)
    val dataBinding = PostsDataBinding.inflate(
        layoutInflater,
        parent,
        false
    )
    return PostsViewHolder(dataBinding)
}

override fun onBindViewHolder(holder: PostsViewHolder, position: Int) {
    val product = getItem(position) ?: return
    holder.bindProduct(product)

    val density = Resources.getSystem().displayMetrics.density

    if (position == 0) {
        holder.itemView.layoutParams.height = 420 * density.toInt()
    } else {
        holder.itemView.layoutParams.height = 450 * density.toInt()
    }
}

companion object : DiffUtil.ItemCallback<PostsModel>() {
    override fun areItemsTheSame(oldItem: PostsModel, newItem: PostsModel): Boolean {
        return oldItem.upload_date == newItem.upload_date
    }

    override fun areContentsTheSame(oldItem: PostsModel, newItem: PostsModel): Boolean {
        return oldItem == newItem
    }
}

inner class PostsViewHolder(
    private val dataBinding: PostsDataBinding
) : RecyclerView.ViewHolder(dataBinding.root) {
    fun bindProduct(product: PostsModel) {
        dataBinding.posts = product
    }
  }
 }

查看 model ->

 @HiltViewModel
 class PostsViewModel @Inject constructor(
private val queryPostsByName: Query
   ) : ViewModel() {
val flow = Pager(
    PagingConfig(
        pageSize = 10
    )
  ) {
    FirestorePagingSource(queryPostsByName)
 }.flow.cachedIn(viewModelScope)
}

片段->

   private fun setProgressBarAccordingToLoadState() {
    dataBinding.rvUserPosts.adapter = adapter
}

private fun getPosts() {
    lifecycleScope.launch {
        viewModel2.flow.collectLatest {
            adapter.submitData(it)

        }
    }
}

private fun setPostsAdapter() {
    lifecycleScope.launch {
        adapter.loadStateFlow.collectLatest {
            dataBinding.progressBar.isVisible = it.append is LoadState.Loading
        }
    }
}

回收站查看项目->

  <?xml version="1.0" encoding="utf-8"?>

<data class="PostsDataBinding">
    <variable
        name="posts"
        type="com.ansh.jetpack.mvvm.data.PostsModel" />
</data>

<androidx.cardview.widget.CardView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="2dp"
    app:cardCornerRadius="8dp">



    <ImageView
        android:id="@+id/ivCover"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"
        app:imageUrl="@{posts.img_hd_url}"
        android:src="@color/cardview_dark_background" />


</androidx.cardview.widget.CardView>

回收站视图->

 <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/rvUserPosts"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical"
          
   app:layoutManager=
      "androidx.recyclerview.widget.StaggeredGridLayoutManager"
                app:spanCount="2"
                tools:listitem="@layout/rv_user_posts_item" />

我认识这段代码,你很可能是从这个资源中得到的:

如何使用 Jetpack Compose 在 Firestore 中实现分页?

由于我写了那篇文章和相应的 代码,我可以向你保证,它不会获取数据库中的所有数据,它只会加载一组 10 个文档,一个接一个。

为什么我认为您会一次获得所有数据? 这仅仅是因为您在数据库中没有足够的文档。

首次启动应用程序时,您会获得 10 个文档。 由于第一个屏幕可以容纳超过 10 个元素,实际上是 12 个,因此完成了另一个请求。 到目前为止,您收到了 20 个文档。 如文章中所述, Paging v3 库包含一个PagingConfig class,它有一个公共构造函数,其中包含一个名为prefetchDistance的参数:

预取距离,它定义了距离加载的内容访问边缘多远才能触发进一步加载。

这基本上意味着,该库会提前加载另外 10 个文档,因此您不会有滞后的体验。 因此,当第一次启动应用程序时,您请求 30 个文档,因为限制设置为 10。如果您在数据库中只有 30 个文档,是的,您正在下载它们,但是如果您有,例如, 100 个文档,您会看到,当您到达第 20 个文档时,又加载了 10 个文档,依此类推,直到您全部获得它们。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM