尝试加载新数据时,Firebase LimitToLast崩溃

时间:2018-08-29 11:56:25

标签: java android firebase listview firebase-realtime-database

我正在尝试将20个用户发布到ListView后加载更多元素(此功能运行良好),但是当我滚动到ListView的底部时,我想加载另外20个用户,但它崩溃了。

这是我到目前为止所做的

FilterData.class

private String oldestUserID;

private void fetchData(DataSnapshot dataSnapshot) {

    mList.clear();

    for (DataSnapshot snapshot : dataSnapshot.getChildren()) {

        oldestUserID = dataSnapshot.getKey();
        userPojo = snapshot.getValue(UserPojo.class);
        String email = userPojo.getEmail();
        mList.add(email);
    }
    fetchSuccessListener.onListFetched(true);
}

public void refillListView(ListView listView) {

    listView.setOnScrollListener(new AbsListView.OnScrollListener() {

        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {
            currentScrollState = scrollState;
            isScrollCompleted();

        }

        @Override
        public void onScroll(AbsListView view, int firstVisibleItem,
                             int visibleItemCount, int totalItemCount) {
            currentFirstVisibleItem = firstVisibleItem;
            currentVisibleItemCount = visibleItemCount;
            totalItem = totalItemCount;

        }

        private void isScrollCompleted() {
            if (totalItem - currentFirstVisibleItem == currentVisibleItemCount
                    && currentScrollState == SCROLL_STATE_IDLE) {

                mDatabase.orderByKey().startAt(oldestUserID).limitToFirst(20).addListenerForSingleValueEvent(new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {
                        fetchData(dataSnapshot);
                    }

                    @Override
                    public void onCancelled(DatabaseError databaseError) {

                    }
                });
            }


        }


    });
}

这是它的工作方式,我使用一个接口来检测何时完成数据提取并通知我的适配器填充ListView,这对于我的前20个用户都可以正常工作,但是当我滚动到最后时,我想要列表中添加新用户(还有20个),但是我收到了这个崩溃日志

  

无法在具有先前设置的限制的查询上调用limitToLast!

现在,这是我如何调用我的方法以获取数据

MainActivity.class

检索数据时填充列表视图的接口(工作正常)

@Override
public void onListFetched(boolean fetched) {
    if(fetched){

        mUserListView.setAdapter(adapter);
        adapter.notifyDataSetChanged();
    }
}

这只是为了知道用户何时滚动并需要再加载20个用户

filterData.refillListView(mUserListView);

我上面想要做的是获取数据库中的最后一个userID,以便在查询完最后一个用户之后开始查询20个新用户,因此我可以再加载20个。

这是我用来获取前20个用户的查询

 mRootDatabase = FirebaseDatabase.getInstance().getReference().child("Usuarios");
        query = mRootDatabase.limitToFirst(20);

Firebase数据库结构如下

Firebase Database

编辑:Logcat错误指向此行

mDatabase.orderByKey().startAt(oldestUserID).limitToFirst(20).....

感谢您的帮助!

编辑:摘要

public void refillListView() {
mQueryDatabase.orderByKey().startAt(oldestUserID).limitToFirst(20).addListenerForSingleValueEvent(new ValueEventListener() {
                        @Override
                        public void onDataChange(DataSnapshot dataSnapshot) {
                            fetchData(dataSnapshot);
                        }

                        @Override
                        public void onCancelled(DatabaseError databaseError) {

                        }
                    });
}

其中private Query mQueryDatabase;与我的构造函数一起传递

public FilterData(Query mQueryDatabase, Context context) {
        this.mQueryDatabase = mQueryDatabase;
        this.userPojo = new UserPojo();
        this.mContext = context;
    }

并像这样填充

  Query query = mRootDatabase.limitToFirst(20);
       FilterData filterData  = new FilterData(query,this);
fetchData(dataSnapshot);提取

oldestUserID

fetchData在哪里

private void fetchData(DataSnapshot dataSnapshot) {

        mList.clear();

        for (DataSnapshot snapshot : dataSnapshot.getChildren()) {

            oldestUserID = snapshot.getKey();
            userPojo = snapshot.getValue(UserPojo.class);
            String email = userPojo.getEmail();
            mList.add(email);
        }
        fetchSuccessListener.onListFetched(true);
    }

2 个答案:

答案 0 :(得分:2)

据我所见,您最初是这样做的:

Query query = mRootDatabase.limitToFirst(20);
FilterData filterData  = new FilterData(query,this);

然后FilterData这样做:

public FilterData(Query mQueryDatabase, Context context) {
    this.mQueryDatabase = mQueryDatabase;
    this.userPojo = new UserPojo();
    this.mContext = context;
}

然后:

mQueryDatabase.orderByKey().startAt(oldestUserID).limitToFirst(20).addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        fetchData(dataSnapshot);
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {
        throw databaseError.toException(); // don't ignore errors
    }
});

在这一点上,如果我们将事物链接在一起,您将拥有:

mRootDatabase
  .limitToFirst(20)
  .orderByKey()
  .startAt(oldestUserID)
  .limitToFirst(20)
  .addListenerForSingleValueEvent(
    ...

并且由于您有两次limitToFirst(20),它说明了为什么会收到错误消息。

我的直觉是您希望将查询的根引用传递到FilterData中,所以:

FilterData filterData  = new FilterData(mRootDatabase,this);

或者,您可以在FilterData之外构建基本查询(查询中所有恒定的部分):

Query query = mRootDatabase.orderByKey().limitToFirst(20);

然后在FilterData中仅添加变量部分(startAt()子句):

mQueryDatabase.startAt(oldestUserID).addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        fetchData(dataSnapshot);
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {
        throw databaseError.toException(); // don't ignore errors
    }
});

答案 1 :(得分:1)

在这里,我完成了Firebase-Chat-Pagination。对此进行检查。它可能会对您有所帮助。

private void loadDataFirst() {
    mUserRefValueEventListener = mConversationRef.child(mLocation)
            .limitToLast(TOTAL_ITEM_EACH_LOAD)
            .orderByKey()
            .addValueEventListener(new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {
                    // It should be null when new meesage sent by own
                    mLastDataSnapshot = null;
                    if (dataSnapshot.exists()) {
                        mChatList.clear();
                        for (DataSnapshot readDataSnapshot : dataSnapshot.getChildren()) {
                            ChatResponse chatModel = readDataSnapshot.getValue(ChatResponse.class);
                            if (chatModel != null) {
                                mChatList.add(chatModel);
                            }
                            // We need First DataSnapshot for pagination
                            if (mLastDataSnapshot == null) {
                                mLastDataSnapshot = readDataSnapshot;
                            }

                        }
                        mView.onFetchMessagesSuccess(mChatList);
                    }
                }

                @Override
                public void onCancelled(DatabaseError databaseError) {

                }
            });

}

 public void loadMoreDataPagination() {

    if (mLastDataSnapshot != null && (mTotalCount == 0 || mView.getChatMessageCount() < mTotalCount)) {
        mUserRefValueEventListener = mConversationRef.child(mLocation)
                .orderByKey()
                .endAt(mLastDataSnapshot.getKey())
                .limitToLast(TOTAL_ITEM_EACH_LOAD)
                .addValueEventListener(new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {


                        if (dataSnapshot.exists()) {
                            mChatList.clear();
                            for (DataSnapshot readDataSnapshot : dataSnapshot.getChildren()) {
                                ChatResponse chatModel = readDataSnapshot.getValue(ChatResponse.class);
                                if (chatModel != null) {
                                    mChatList.add(chatModel);
                                }
                                // We need Last DataSnapshot for pagination while load more
                                if (mChatList.size() == 1) {
                                    mLastDataSnapshot = readDataSnapshot;
                                }
                            }
                            // One item duplicates from last list so need to Remove it
                            mChatList.remove(mChatList.size() - 1);
                            mView.onFetchLoadMoreSuccess(mChatList, mTotalCount);

                        }
                    }

                    @Override
                    public void onCancelled(DatabaseError databaseError) {
                        mView.hideLoading();
                    }
                });
    }
}