Reverse Pagination in chat app not working

androidXP :

I have RecyclerView which i am using for chat and all is working but reverse pagination like loading chat history from local SQLitedatabase is not working like Whatsapp Or Telegram App.

At first load i am loading user chat history by default with only 10 messages from Local SQLite Database. If i pull from top it loads next(older) 10 messages and so on.

I am using Firebase Realtime Database as our chat server which sync in realtime and when user send new message it fetch message and add into SQLite Database then loads at above oldest message Like in Image below

enter image description here enter image description here

Main Class

@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;

        }
    }

Chat Adapter

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 Query

//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;
}
Oussema Aroua :

Using message.add(chat_wrapper); will put the added element to the end of the list so it will be shown at the end of the list while you are reversing the Recycler , use message.add(0,chat_wrapper); so it will be at the beginning of the array list.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=105371&siteId=1