首页 > 解决方案 > 回收站聊天分页在顶部添加新消息

问题描述

我正在开发一个聊天应用程序,我需要在其中显示反向分页并在用户向上滚动时显示用户以前的聊天记录。

我首先从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);
    }
}

我也做了这样RecyclerViewLayoutManager设置

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;
            }
        }
    }
});

并将另一个加载到屏幕中。

代码中的问题

在此处输入图像描述

更新:我注意到我的最新消息在数组 [0] 中有索引号,而我在滚动到最旧消息 [21] 后的最后一条消息。因此,当我在我的聊天框中输入新消息时,它会分配给数组中的 [22],并在最旧的消息上方而不是屏幕底部显示。

在此处输入图像描述

标签: javaandroidsqlandroid-recyclerviewpagination

解决方案


每当您在聊天屏幕中添加新项目时,不要使用message.add(Video);添加项目message.add(0,Video);,这将在屏幕底部添加项目然后添加屏幕顶部。它将被添加到数组的起始位置,即[0]


推荐阅读