我有RecyclerView
可以用于聊天,并且一切正常,但是反向分页(例如从本地SQLite
数据库加载聊天记录)不能像Whatsapp或Telegram App一样工作。
在第一次加载时,默认情况下,我正在从本地SQLite
数据库仅加载10条消息的用户聊天记录。如果我从顶部拉,它将加载下一条(旧的)10条消息,依此类推。
我使用Firebase Realtime Database
作为我们的聊天服务器,该服务器实时同步,并且当用户发送新消息时,它将获取消息并添加到SQLite Database
中,然后加载到最旧的消息上,如下面的图片中所示
主班
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.chat_screen_main_fragment, container, false);
setRetainInstance(true);
// RECYCLER VIEW
recyclerView = v.findViewById(R.id.Chat_Screen_Message_List);
layoutManager = new LinearLayoutManager(getActivity());
layoutManager.scrollToPosition(message.size() - 1);
if (adapter == null) {
adapter = new Chat_Adapter(getActivity(), message);
}
layoutManager.setStackFromEnd(true);
layoutManager.setReverseLayout(true);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);
chat_database=new Chat_Database(getActivity());
// Testing For Pagination
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 "+OFFSET);
if (chatCount > OFFSET){
Log.d(TAG,"Total item count is more than database = "+chatCount +" "+OFFSET);
new databaseAsync().execute();
isScrolling = false;
}
}
}
});
}
//THIS METHOD WILL FETCH ALL MESSAGES FROM FIREBASE DATABASE
private synchronized void append_chat_conversation(DataSnapshot dataSnapshot) {
Iterator iterator = dataSnapshot.getChildren().iterator();
while (iterator.hasNext()) {
// NOW GET ALL DATA FROM FIREBASE DATABASE AND SAVE IT INTO STRINGS THEN CHECK EACH BY ITS MESSAGE TYPE
Chat_Msg = (String) ((DataSnapshot) iterator.next()).getValue();
Chat_FROM = (String) ((DataSnapshot) iterator.next()).getValue();
Chat_TO = (String) ((DataSnapshot) iterator.next()).getValue();
Chat_Type= (String) ((DataSnapshot) iterator.next()).getValue();
if (Chat_Type.equals("Local_Image")) {
long id = chat_database.Insert_Chat(Session.getUserID(), "Image", Chat_Msg);
if (id==0){
return;
}
Chat_Wrapper image = new Chat_Wrapper(null, Chat_Msg, null, null, null, null, null, Chat_TimeStamp,id );
message.add(image);
adapter.notifyDataSetChanged();
recyclerView.post(new Runnable() {
@Override
public void run() {
recyclerView.smoothScrollToPosition(adapter.getItemCount());
}
});
} else if (Chat_Type.equals("Typed_Message")){
long id=chat_database.Insert_Chat(Session.getUserID(),"Text", Chat_Msg);
//Adding Chat Data Into Database
if (id==0){
return;
}
Chat_Wrapper chat_wrapper = new Chat_Wrapper(Chat_Msg, null, null, null, null, null, null, Chat_TimeStamp,id);
message.add(chat_wrapper);
adapter.notifyDataSetChanged();
recyclerView.post(new Runnable() {
@Override
public void run() {
recyclerView.smoothScrollToPosition(adapter.getItemCount());
}
});
}
}
//FETCHING DATA FROM LOCAL DATABASE
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 "+OFFSET);
if (OFFSET == 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,OFFSET);
chatCursor.moveToFirst();
}
@Override
protected Void doInBackground(Void... voids) {
if (checkDB_Exist && chatCursor.getCount()>0) {
chatCursor.moveToFirst();
do {
database_rowID = chatCursor.getInt(chatCursor.getColumnIndex("ID"));
database_userID = chatCursor.getString(chatCursor.getColumnIndex("USER_ID"));
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"));
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("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);
}
}
}
while (chatCursor.moveToNext()) ;
chatCursor.close();
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
recyclerView.getLayoutManager().onRestoreInstanceState(recyclerViewState);
adapter.notifyDataSetChanged();
OFFSET +=10;
}
}
聊天适配器
public class Chat_Adapter extends RecyclerView.Adapter<Chat_Adapter.ViewHolder> {
Chat_Wrapper chat_wrapper;
//ARRAYLIST OF MESSAGES OBJECT CONTAINING ALL THE MESSAGES IN THE THREAD
List<Chat_Wrapper> arrayList_message;
public Chat_Adapter(Context context, List<Chat_Wrapper> message) {
this.context = context;
this.arrayList_message = message;
}
@Override
public Chat_Adapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View Layout;
Log.d(TAG,"On Create View Holder Calling ");
if (viewType==1){
Log.d(TAG,"View Tyoe Is "+viewType);
Layout=LayoutInflater.from(parent.getContext()).inflate(R.layout.chat_screen_message_item,parent,false);
// ImagePath=Session.getUserImage();
}
else {
Log.d(TAG,"View Type Is "+viewType);
Layout=LayoutInflater.from(parent.getContext()).inflate(R.layout.chat_screen_message_item_other,parent,false);
// ImagePath=chat_wrapper.getImageView();
}
return new ViewHolder(Layout);
}
@Override
public void onBindViewHolder(final Chat_Adapter.ViewHolder holder, final int position) {
chat_wrapper=arrayList_message.get(position);
context=holder.itemView.getContext();
if (valueofImage){
// Showing Sent User Image in thumbnail
Glide.with(context).load(chat_wrapper.getImageSent()).apply(new RequestOptions()
.fitCenter()
.skipMemoryCache(true))
.thumbnail(0.1f)
.into(holder.Sent_Image);
}
}
else if (valueofMessage){
Log.d(TAG,"Value Of Message Running ImagePath "+ImagePath);
holder.Sent_Video.setVisibility(View.GONE);
holder.Sent_Image.setVisibility(View.GONE);
holder.TimeStampImage.setVisibility(View.GONE);
holder.TimeStampDoc.setVisibility(View.GONE);
holder.TimeStampVideo.setVisibility(View.GONE);
holder.Search_title.setVisibility(View.GONE);
holder.Search_link.setVisibility(View.GONE);
holder.Search_snippet.setVisibility(View.GONE);
holder.Google_Image.setVisibility(View.GONE);
holder.videoView.setVisibility(View.GONE);
holder.Doc_FileName.setVisibility(View.GONE);
holder.Doc_ImageView.setVisibility(View.GONE);
holder.Doc_FileSize.setVisibility(View.GONE);
holder.GeoFencing_Layout.setVisibility(View.GONE);
holder.GeoFencing_Image.setVisibility(View.GONE);
holder.GeoFencing_LatLng.setVisibility(View.GONE);
holder.Message.setVisibility(View.VISIBLE);
holder.TimeStamp.setVisibility(View.VISIBLE);
holder.User_Image.setVisibility(View.VISIBLE);
//CHECK SENDER IS SAME AS LOGGED IN USER
if ((Session.getUserFname()+" "+Session.getUserLname()).equals(chat_wrapper.getSender_UserName())){
ImagePath=Session.getUserImage();
Log.d(TAG,"Session.getUserImage() "+Session.getUserImage());
Log.d(TAG,"Value Of Message Running ImagePath "+ImagePath);
}
else {
holder.Message.setText(chat_wrapper.getMessage());
holder.TimeStamp.setText(chat_wrapper.getTimestamp());
}
@Override
public int getItemCount() {
Log.d(TAG,"GET ITEM COUNT--Array Message List Size "+arrayList_message.size());
return arrayList_message.size();
}
}
SQLite查询
//This method will get row by limit
public Cursor getLimitUserChat(String UserID,int nextChat){
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;
}
答案 0 :(得分:1)
使用message.add(chat_wrapper);
会将添加的元素放在列表的末尾,以便在反转Recycler
时将其显示在列表的末尾,请使用message.add(0,chat_wrapper);
这样将在数组列表的开头。