如何在android Firestore上实现Paginate查询[重复]

问题描述 投票:0回答:2

这个问题在这里已有答案:

在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
                    // ...
                }
            });

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

//使用查询进行分页

// ...

更新:我正在基于关于Paginate query的firestore doc工作并且看看possible duplicate of another question我没有让它完成工作

谢谢

android firebase android-recyclerview pagination google-cloud-firestore
2个回答
0
投票

在这里我找到了解决方案但不是更好的一个,如果有更好的方法请发布

通过在加载更多节点之前保存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);

            }
        }
    });

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


0
投票

我已经扩展了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. 通过调用setQuery(Query)清除mIdentifier.clear()方法中的标识符
  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
© www.soinside.com 2019 - 2024. All rights reserved.