【问题标题】:How to Implement Paginate a query on android Firestore [duplicate]如何在android Firestore上实现分页查询[重复]
【发布时间】:2018-06-05 07:58:24
【问题描述】:

关于从 GitHub friendly eat app 学习 firebase firestore 的示例

我想实现分页以限制 10 个节点

private static final int LIMIT = 10;

在 firestore 示例应用程序中,mAdapter 加载数据/节点如下

mFirestore = FirebaseFirestore.getInstance();

    // Get ${LIMIT} restaurants
    mQuery = mFirestore.collection("restaurants")
            .orderBy("avgRating", Query.Direction.DESCENDING)
            .limit(LIMIT);

    // RecyclerView
    mAdapter = new RestaurantAdapter(mQuery, this) {
        @Override
        protected void onDataChanged() {
            // Show/hide content if the query returns empty.
            if (getItemCount() == 0) {
                mRestaurantsRecycler.setVisibility(View.GONE);
                mEmptyView.setVisibility(View.VISIBLE);
            } else {
                mRestaurantsRecycler.setVisibility(View.VISIBLE);
                mEmptyView.setVisibility(View.GONE);
            }
        }

        @Override
        protected void onError(FirebaseFirestoreException e) {
            // Show a snackbar on errors
            Snackbar.make(findViewById(android.R.id.content),
                    "Error: check logs for info.", Snackbar.LENGTH_LONG).show();
        }
    };

    mRestaurantsRecycler.setLayoutManager(new LinearLayoutManager(this));
    mRestaurantsRecycler.setAdapter(mAdapter);

    // Filter Dialog
    mFilterDialog = new FilterDialogFragment();
}

@Override
public void onStart() {
    super.onStart();

    // Start sign in if necessary
    if (shouldStartSignIn()) {
        startSignIn();
        return;
    }

    // Apply filters
    onFilter(mViewModel.getFilters());

    // Start listening for Firestore updates
    if (mAdapter != null) {
        mAdapter.startListening();
    }
}

firestore 文档上说要分页

// Construct query for first 25 cities, ordered by population
    Query first = db.collection("cities")
            .orderBy("population")
            .limit(25);

    first.get()
            .addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
                @Override
                public void onSuccess(QuerySnapshot documentSnapshots) {
                    // ...

                    // Get the last visible document
                    DocumentSnapshot lastVisible = 
                    documentSnapshots.getDocuments()
                            .get(documentSnapshots.size() -1);

                    // Construct a new query starting at this document,
                    // get the next 25 cities.
                    Query next = db.collection("cities")
                            .orderBy("population")
                            .startAfter(lastVisible)
                            .limit(25);

                    // Use the query for pagination
                    // ...
                }
            });

结合上面的代码,我应该如何实现分页来加载超过 10 当我滚动到回收器视图底部时要加载的节点

// 使用查询进行分页

// ...

更新:我正在根据有关 Paginate query 的 firestore 文档工作,并查看 possible duplicate of another question 我没有完成工作

谢谢

【问题讨论】:

标签: android firebase android-recyclerview pagination google-cloud-firestore


【解决方案1】:

我已将FirestoreAdapter 扩展如下:

  1. 跟踪 DocumentSnapshots 标识符。
private Set<String> mIdentifier = new HashSet<>();
  1. 为分页添加一个新的公共方法,因为我希望查询的其余部分保持不变,给定的查询不需要更改
/**
 * Extends the query to load even more data rows. This method will do nothing if the query has
 * not yet been set.
 * @param limit the new limit
 */
public void paginate(long limit) {
    if (mQuery != null) {
        if (mRegistration != null) {
            mRegistration.remove();
            mRegistration = null;
        }
        // Expect the query to stay the same, only the limit will change
        mQuery = mQuery.limit(limit);
        startListening();
    }
}
  1. 通过调用mIdentifier.clear()清除setQuery(Query)方法中的标识符
  2. 如下采用onDocumentAdded(DocumentChange)onDocumentRemoved(DocumentChange)
protected void onDocumentAdded(DocumentChange change) {
    if (!mIdentifier.contains(change.getDocument().getId())) {
        mSnapshots.add(change.getNewIndex(), change.getDocument());
        mIdentifier.add(change.getDocument().getId());
        notifyItemInserted(change.getNewIndex());
    }
}
protected void onDocumentRemoved(DocumentChange change) {
    mSnapshots.remove(change.getOldIndex());
    mIdentifier.remove(change.getDocument().getId());
    notifyItemRemoved(change.getOldIndex());
}
  1. 对于 onScrolling 监听器,我坚持使用本指南:Endless Scrolling with AdapterViews and RecyclerView

【讨论】:

  • 谢谢...看起来不错,但我需要时间解释自己并实施,一定会尝试这个
  • 你好@Peter A,我正在使用firebase firestore UI,并在getSnapshots().add(change.getNewIndex(), change.getNewIndex());下方的代码中尝试了上面的代码,显示错误第二个参数类型错误。找到:“com.google.firebase.firestore.DocumentSnapshot”,需要:“com.domain.appname.model”
【解决方案2】:

在这里我找到了解决方案,但没有更好的解决方案,如果有更好的方法请发帖

通过在加载更多节点之前保存 RecyclerView 状态并在增加限制后重新加载 RecyclerView 状态

private static final int LIMIT = 10;

改为

private int LIMIT = 10;

当recyclerView滚动到底部时

mRestaurantsRecycler.addOnScrollListener(new RecyclerView.OnScrollListener() {

        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);

            final int mLastVisibleItemPosition = mManager.findLastVisibleItemPosition();

            if ( mLastVisibleItemPosition == (LIMIT-1)) {
                LIMIT = LIMIT*2;
                showSpotDialog();

                // save RecyclerView state
                mBundleRecyclerViewState = new Bundle();
                Parcelable listState = mRestaurantsRecycler.getLayoutManager().onSaveInstanceState();
                mBundleRecyclerViewState.putParcelable(KEY_RECYCLER_STATE, listState);

                loadMore(query);
                new Handler().postDelayed(new Runnable() {

                    @Override
                    public void run() {

                        // restore RecyclerView state
                        if (mBundleRecyclerViewState != null) {
                            Parcelable listState = mBundleRecyclerViewState.getParcelable(KEY_RECYCLER_STATE);
                            mRestaurantsRecycler.getLayoutManager().onRestoreInstanceState(listState);
                        }

                        hideSpotDialog();
                    }

                }, 500);

            }
        }
    });

在限制之后加载节点时看起来很不寻常,但现在没有办法...... 是的,我正在寻找加载更多没有缺陷的节点

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-17
    • 1970-01-01
    • 1970-01-01
    • 2018-09-15
    • 2014-03-05
    • 2018-04-11
    相关资源
    最近更新 更多