Java 回收器聊天分页在顶部添加新消息
我正在开发一个聊天应用程序,我需要显示反向分页,并在用户向上滚动时显示用户以前的聊天记录 我首先从Java 回收器聊天分页在顶部添加新消息,java,android,sql,android-recyclerview,pagination,Java,Android,Sql,Android Recyclerview,Pagination,我正在开发一个聊天应用程序,我需要显示反向分页,并在用户向上滚动时显示用户以前的聊天记录 我首先从SQLite数据库加载数据,以显示用户的最后10条消息 public Cursor getLimitUserChat(String UserID,int nextChat){ Log.d(TAG,"Get Single Row Running= ID "+UserID); database=this.getReadableDatabase(); cursor = databa
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);
}
}
在第一次加载时,它从本地数据库获取总共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)代码>分页按需工作,但新消息堆叠在最旧消息的顶部
- 设置
更新 现在我认为,问题在于数据库查询。我假设,每当键入新消息时,它都以最高的
ID
存储在数据库中,这使它成为数据库表组织中的最新消息。因此,如果正确设置偏移量,则getLimitUserChat
永远不会返回最新消息
我不知道
dataBaseAsync.execute
函数做什么。我假设,它会在ArrayList
中添加更多元素,并调用notifyDateSetChanged
因此,如果将新获取的数据添加到ArrayList
中是正确的,则应按正确的顺序将数据填充到RecyclerView
中。但是,您可能还注意到,每次添加新的分页数据时,您的RecyclerView
可能会随着反向布局的启用而滚动到底部,这对于聊天应用程序来说可能是不需要的
因此,要在加载新数据之前将RecyclerView
保持在同一位置,您需要保存RecyclerView
的状态,并在获取新数据时恢复状态。下面是存储RecyclerView
状态并返回到相同状态的代码
// Save state
private Parcelable recyclerViewState;
recyclerViewState = recyclerView.getLayoutManager().onSaveInstanceState();
// Restore state
recyclerView.getLayoutManager().onRestoreInstanceState(recyclerViewState);
我建议您设置LayoutManager
,如下所示
layoutManager.setReverseLayout(true);
layoutManager.setStackFromEnd(true);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);
请仔细检查ArrayList
是否正确填充(即列表顶部的新数据和底部的旧数据)
希望有帮助
请从您的onPostExecute
中删除以下内容
if (message.size() > 2){
recyclerView.smoothScrollToPosition(message.size()-1);
} else {
recyclerView.smoothScrollToPosition(layoutManager.getItemCount());
}
并在
预执行
中添加必要的null
检查 无论何时在聊天屏幕中添加新项目,都不要使用消息。添加(视频)代码>改为添加项目消息。添加(0,视频)代码>将在屏幕底部添加项目,然后在屏幕顶部添加项目。它将被添加到数组的起始位置,即[0]
数据库异步
是一项异步任务,用于从SQLite数据库获取条目以及从数据库获取并向arraylist添加数据。我理解,请检查数据是否如我在回答中所述正确添加。如果答案有帮助,请告诉我。:)我的新数据仍在添加旧消息。我在AsyncTask的PreExecute
和postexecute
保存了回收器状态。您是否也执行了我为布局管理器建议的更改?是的,请在ArrayList
中发布添加新项目的代码并进行分页。我已经更新了答案。你能看一下吗?我正在调试你的代码,如果我又出错了,我会发布更新。我建议你使用新的Android分页库,而不是使用滚动侦听器。这是非常令人满意的。然后,您可以查看这个答案,并为您的应用程序修改它。@ergenersay,这不是分页问题。正如用户所说,分页工作正常,但有数据显示错误的位置,其更多的是数组和sqlite问题,而不是分页。我想您正在寻找类似的内容。@Abbas您是对的,但您能让我知道如何根据我的代码执行此操作吗?我从来不知道解决方案有这么简单。非常感谢亲爱的
if (message.size() > 2){
recyclerView.smoothScrollToPosition(message.size()-1);
} else {
recyclerView.smoothScrollToPosition(layoutManager.getItemCount());
}