我正在尝试将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数据库结构如下
编辑: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);
}
答案 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();
}
});
}
}