我正在开发一个聊天应用程序,我需要在其中显示反向分页并在用户向上滚动时显示用户之前的聊天记录。
我首先从 SQLite
数据库加载数据以显示用户的最后 10 条消息。
public Cursor getLimitUserChat(String UserID,int nextChat){
Log.d(TAG,"Get Single Row Running= ID "+UserID);
database=this.getReadableDatabase();
cursor = database.rawQuery("SELECT * FROM " + TABLE_NAME + " Where "+ RECEIVER_USERID +"="+ UserID+" ORDER BY ID DESC LIMIT 10 OFFSET "+nextChat,null);
return cursor;
}
然后我将光标添加到自定义 ArrayList
private class databaseAsync extends AsyncTask<Void,Void,Void> {
boolean checkDB_Exist,chatItemsCounts;
private Parcelable recyclerViewState;
@Override
protected void onPreExecute() {
super.onPreExecute();
Log.d(TAG,"Chat Database Function "+databaseChatValue);
if (databaseChatValue == 0){
message.clear();
}
recyclerViewState = recyclerView.getLayoutManager().onSaveInstanceState();
//chatCursor=chat_database.getUserChat(UserID_Intent);
chatCount = chat_database.getUserChatCount(UserID_Intent);
chatCursor=chat_database.getLimitUserChat(UserID_Intent,databaseChatValue);
checkDB_Exist=functions.DatabaseExist(getActivity(),"CHAT_DATABASE.DB");
chatItemsCounts=chatCursor.getCount()>0;
chatCursor.moveToFirst();
Log.d(TAG,"Chat Cursor "+ chatCursor.getCount());
Log.d(TAG,"Total Chat Counts "+chatCount);
}
@Override
protected Void doInBackground(Void... voids) {
if (checkDB_Exist && chatCursor.getCount()>0 && chatCursor.getString(chatCursor.getColumnIndex("RECEIVER_USER_ID")).equals(UserID_Intent)) {
chatCursor.moveToFirst();
do {
database_rowID = chatCursor.getInt(chatCursor.getColumnIndex("ID"));
database_userID = chatCursor.getString(chatCursor.getColumnIndex("USER_ID"));
database_RoomName = chatCursor.getString(chatCursor.getColumnIndex("ROOM_NAME"));
database_ReceiverID = chatCursor.getString(chatCursor.getColumnIndex("RECEIVER_USER_ID"));
database_MessageType = chatCursor.getString(chatCursor.getColumnIndex("MESSAGE_TYPE"));
database_Message = chatCursor.getString(chatCursor.getColumnIndex("USER_MESSAGE"));
database_MsgFrom = chatCursor.getString(chatCursor.getColumnIndex("SENDER_NAME"));
database_MsgTo = chatCursor.getString(chatCursor.getColumnIndex("RECEIVER_NAME"));
database_TimeStamp = chatCursor.getString(chatCursor.getColumnIndex("TIME_STAMP"));
database_FCMfrom = chatCursor.getString(chatCursor.getColumnIndex("SENDER_TOKEN"));
database_FCMto = chatCursor.getString(chatCursor.getColumnIndex("RECEIVER_TOKEN"));
database_LocalPath = chatCursor.getString(chatCursor.getColumnIndex("DOWNLOADED_AT"));
database_PhoneFrom = chatCursor.getString(chatCursor.getColumnIndex("MY_PHONE"));
database_PhoneTo = chatCursor.getString(chatCursor.getColumnIndex("OTHER_PHONE"));
Log.d(TAG, "Value Of Database Message String = " + database_Message);
Log.d(TAG, "Row ID of Database " + database_rowID);
// Check Message Type
if (true) {
if (database_MessageType.equals("Image")) {
Log.d(TAG, "Message Type Is Image");
Log.d(TAG, "Row ID of Database " + database_rowID);
Chat_Wrapper image = new Chat_Wrapper(null, database_Message, null, null, null, null, null, database_TimeStamp, database_PhoneTo, UserImage_Intent, database_MsgFrom, null, null, database_rowID);
message.add(image);
} else if (database_MessageType.equals("GIF")) {
Chat_Wrapper image = new Chat_Wrapper(null, database_Message, null, null, null, null, null, database_TimeStamp, database_PhoneTo, UserImage_Intent, database_MsgFrom, null, null, database_rowID);
message.add(image);
} else if (database_MessageType.equals("Video") || (database_MessageType.equals("Youtube_Video"))) {
Log.d(TAG, "Message Type Is Video");
Chat_Wrapper Video = new Chat_Wrapper(null, null, database_Message, null, null, null, null, database_TimeStamp, database_PhoneTo, UserImage_Intent, database_MsgFrom, null, null, database_rowID);
message.add(Video);
} else if (database_MessageType.equals("Audio")) {
Log.d(TAG, "Message Type Is Audio");
Chat_Wrapper Audio = new Chat_Wrapper(null, null, null, database_Message, null, null, null, database_TimeStamp, database_PhoneTo, UserImage_Intent, database_MsgFrom, null, null, database_rowID);
message.add(Audio);
} else if (database_MessageType.equals("Documents")) {
Log.d(TAG, "Message Type Is Documents");
Chat_Wrapper Docs = new Chat_Wrapper(null, null, null, null, database_Message, null, null, database_TimeStamp, database_PhoneTo, UserImage_Intent, database_MsgFrom, null, null, database_rowID);
message.add(Docs);
} else if (database_MessageType.equals("Location")) {
Log.d(TAG, "Message Type Is Location");
Chat_Wrapper Location = new Chat_Wrapper(null, null, null, null, null, database_Message, null, database_TimeStamp, database_PhoneTo, UserImage_Intent, database_MsgFrom, null, null, database_rowID);
message.add(Location);
} else if (database_MessageType.equals("Geofence")) {
Log.d(TAG, "Message Type Is Geofence");
Chat_Wrapper GeoFence = new Chat_Wrapper(null, null, null, null, null, null, null, Chat_TimeStamp, UserPhone_Intent, UserImage_Intent, database_MsgFrom, database_Message, null, database_rowID);
message.add(GeoFence);
} else if (database_MessageType.equals("Contacts")) {
Log.d(TAG, "Message Type Is Contacts");
Chat_Wrapper Contacts = new Chat_Wrapper(null, null, null, null, null, null, database_Message, database_TimeStamp, database_PhoneTo, UserImage_Intent, database_MsgFrom, null, null, database_rowID);
message.add(Contacts);
} else if (database_MessageType.equals("Online Media")) {
Log.d(TAG, "Message Type Is Online Media");
Chat_Wrapper Online_Media = new Chat_Wrapper(null, null, database_Message, null, null, null, null, database_TimeStamp, database_PhoneTo, UserImage_Intent, database_MsgFrom, null, null, database_rowID);
message.add(Online_Media);
} else if (database_MessageType.equals("Text")) {
Log.d(TAG, "Message Type Is Text");
Chat_Wrapper text = new Chat_Wrapper(database_Message, null, null, null, null, null, null, database_TimeStamp, database_PhoneTo, UserImage_Intent, database_MsgFrom, null, null, database_rowID);
message.add(text);
} else if (database_MessageType.equals("Google_Search")) {
Log.d(TAG, "Message Type Is Google Search");
List<String> gSearch = new ArrayList<>();
gSearch.add(database_Message);
Chat_Wrapper GoogleSearch = new Chat_Wrapper(null, null, null, null, null, null, null, database_TimeStamp, database_PhoneTo, UserImage_Intent, database_MsgFrom, null, gSearch, database_rowID);
message.add(GoogleSearch);
}
}
}
while (chatCursor.moveToNext()) ;
Room_Name_Intent = database_RoomName;
chatCursor.close();
boolean value = chat_database.isDatabaseClose();
Log.d(TAG, "Value Of Database Close or Not " + value);
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
recyclerView.getLayoutManager().onRestoreInstanceState(recyclerViewState);
adapter.notifyDataSetChanged();
if (message.size()>2){
recyclerView.smoothScrollToPosition(message.size()-1);
}else {
recyclerView.smoothScrollToPosition(layoutManager.getItemCount());
}
Log.d(TAG,"Chat Database "+database_OFFSET);
database_OFFSET +=10;
Log.d(TAG,"Chat Database "+database_OFFSET);
}
}
我也做了这样的RecyclerView
和LayoutManager
设置
layoutManager.setStackFromEnd(true);
layoutManager.setReverseLayout(true);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);
在第一次加载时,它从本地数据库中获取总共 10 个结果,但是一旦它首先加载到屏幕上,它就会以正确的顺序加载(最新消息在最后,旧消息在顶部)。但是 RecyclerView
不会自动滚动到底部。一开始,它从顶部加载,当我滚动时它调用以下方法。
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL){
Log.d(TAG,"Hello I am scrolling screen ");
isScrolling = true;
}
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
currentVisible = layoutManager.getChildCount();
TotalItems = layoutManager.getItemCount();
scrolledOutItems = layoutManager.findFirstVisibleItemPosition();
int check = TotalItems - currentVisible+scrolledOutItems;
Log.d(TAG,"Current Visible = "+currentVisible+" Total = "+TotalItems+" Scrolled Out Items = "+scrolledOutItems+" Check = "+check);
if (isScrolling && TotalItems == currentVisible + scrolledOutItems ){
Log.d(TAG,"Fetch Data Now "+databaseChatValue);
if (chatCount > databaseChatValue){
Log.d(TAG,"Total item count is more than database = "+chatCount +" "+databaseChatValue);
new databaseAsync().execute();
isScrolling = false;
}
}
}
});
然后将另一个载入屏幕。
代码中的问题
- 当设置
layoutManager.setStackFromEnd(true);
时没有layoutManager.setReverseLayout(true);
分页在最后一条消息的底部工作,新消息也在底部添加- 当设置
layoutManager.setReverseLayout(true);
时,分页按要求工作,但新消息堆叠在最旧消息的顶部。
- 当设置
更新:我注意到我最新的消息在数组 [0] 中有索引号,而我的最后一条消息在滚动到最旧的消息后 [21]。因此,当我在聊天框中输入新消息时,它会分配给数组中的 [22],并在屏幕顶部而不是屏幕底部显示最旧消息的上方。
最佳答案
每当您向聊天屏幕(数组列表)添加新项目时,不要使用 message.add(Video);
而是像这样在 0 位置添加项目 message.add(0,Video );
这将在屏幕底部(数组列表顶部)添加项目,而不是在屏幕顶部(数组列表最后)添加项目。它将被添加到数组的起始位置,即 [0]
在您的情况下。
关于java - 回收商聊天分页在顶部添加新消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55115902/