Recyclerview适配器的notifyDataSetChanged不更新RecyclerView [英] Recyclerview Adapter's notifyDataSetChanged not updating RecyclerView

查看:105
本文介绍了Recyclerview适配器的notifyDataSetChanged不更新RecyclerView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个用于聊天应用程序的 RecyclerView ,带有firebase实时数据库和本地SQLite数据库。我将消息保存到本地数据库(SQLite)中,然后调用 adapter.notifyDataSetChanged()

I have a RecyclerView for chat app with firebase realtime database and local SQLite database. I am saving message into local database (SQLite) then calling adapter.notifyDataSetChanged().

如果消息为已经存在于数据库中(消息唯一ID),则SQLite将在数据库 insertOrThrow 方法上返回0。我正在检查像这样的可用性。

If the message is already in the database (message unique id) then SQLite will return 0 on database insertOrThrow method. I am checking the availability like this.

if (id == 0) {
    Log.d(TAG,"Database Already Has Value Of This Random Id ");
    adapter.notifyDataSetChanged();
} else {
    Chat_Wrapper chat_wrapper = new Chat_Wrapper(Chat_Msg, null, null, null, null, null, null, Chat_TimeStamp, UserPhone_Intent, UserImage_Intent, Chat_FROM, null,null,id);
    message.add(chat_wrapper);
    adapter.notifyDataSetChanged();
}

但是,即使 else 语句被调用,我的 RecyclerView 屏幕未更新,但是在后台,如果我键入或收到任何消息,它将保存到本地数据库中但不显示

However, even the else statement is being called, my RecyclerView screen is not updated, but in the background, if I type or receive any message it saves into the local database but doesn't show on screen.

聊天 RecyclerView 在以下情况下有效


  1. 当我从最近的应用程序中清除应用程序

  2. 停止从本地数据库中获取数据

  3. 首次启动聊天屏幕

当我从通知中直接进入聊天屏幕时,我面临着这个问题。

I am facing this issue when I come directly to chat screen from notification.

这就是我正常加载聊天片段的方式。

That's How I load chat fragment normally.

getFragmentManager()。beginTransaction()。add(R.id.Navigation_Drawer,chatFragment) .commit();

通知中加载片段 使用 Asynctask

((Navigation_Drawer)context).getFragmentManager().beginTransaction().replace(R.id.Navigation_Drawer, chatFragment).commit();

这就是我从通知中启动ChatFragment的方式。

That's how i launches ChatFragment from notification.

public class FireBase_Messaging_Service extends FirebaseMessagingService {

    public static final String TAG="###FireBase MSG###";
    public static final int NOTIFICATION=5;
    String UserName;
    String ID;
    String Msg;

    Map<String,String> data;
    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        super.onMessageReceived(remoteMessage);
        Log.d(TAG,"From "+remoteMessage.getFrom());
        if (remoteMessage.getData().size()>0){
            data = remoteMessage.getData();
            Log.d(TAG,"Message Data "+remoteMessage.getData());
            data = remoteMessage.getData();

            UserName = data.get("name");
            ID = data.get("ID");
            Msg = data.get("Message");

            showNotification(Msg,ID,UserName);
        }

        if (remoteMessage.getNotification()!=null){
            Log.d(TAG,"Message Notification Body "+remoteMessage.getNotification().getBody());
           // Toast.makeText(this, "Notification "+remoteMessage.getNotification().getBody(), Toast.LENGTH_LONG).show();
        }
    }

    private void showNotification(String Message,String ID,String UserName) {
        Log.d(TAG,"Show Notification "+Message+" "+ID);
        Intent intent=new Intent(this, Navigation_Drawer.class);
        intent.putExtra("Type","Text");
        //intent.putExtra("Type",MsgType);
        intent.putExtra("ID",ID);
        intent.putExtra("uname",UserName);
        intent.putExtra("Message",Msg);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
        PendingIntent pendingIntent=PendingIntent.getActivity(this,NOTIFICATION,intent,PendingIntent.FLAG_UPDATE_CURRENT);
        int color = getResources().getColor(R.color.black);
        String ChannelID = "Message";
        notificationChannel(ChannelID,"Chat");
        NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext(),ChannelID)
                .setSmallIcon(R.drawable.default_x)
                .setColor(color)
                .setContentTitle(UserName)
                .setContentText(Message)
                .setChannelId(ChannelID)
                .setTicker("My App")
                .setDefaults(Notification.DEFAULT_VIBRATE | Notification.DEFAULT_SOUND | Notification.FLAG_SHOW_LIGHTS)
                .setLights(0xff00ff00, 1000, 500) // To change Light Colors
                .setStyle(new NotificationCompat.BigTextStyle().bigText(Message))//For Expandable View
                .setPriority(NotificationCompat.PRIORITY_DEFAULT)
                .setContentIntent(pendingIntent)
                .setAutoCancel(true);

        NotificationManagerCompat managerCompat = NotificationManagerCompat.from(this);
        managerCompat.notify(NOTIFICATION,builder.build());
    }

    @Override
    public void onDeletedMessages() {
        super.onDeletedMessages();
    }

    private void notificationChannel (String ChannelID, String channelName) {
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            NotificationChannel  channel = new NotificationChannel(ChannelID,channelName, NotificationManager.IMPORTANCE_DEFAULT);
            channel.setLightColor(Color.GREEN);
            NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
            notificationManager.createNotificationChannel(channel);
        }
    }
}

我还注意到,将数据添加到列表 message.add(chat_wrapper)后,它首先显示大小增加,但是当while循环结束时,它显示 ArrayList 。

I also noticed by logging that after adding data to list message.add(chat_wrapper) it first showing an increase in size but when while loop is over, it shows the last size of the ArrayList.

这是 ChatFragment 类。

 public class Chat_Screen_Fragment extends Fragment implements View.OnClickListener, ChildEventListener{

    public static final String TAG = "###CHAT SCREEN###";
    List<Chat_Wrapper> message = new ArrayList<>();

    Chat_Adapter adapter;
    RecyclerView recyclerView;
    LinearLayoutManager layoutManager;

    @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);
        // GET INTENT VALUES FROM USER PROFILE CLASS

        UserName_Intent = getArguments().getString("Get_Name");
        UserImage_Intent = getArguments().getString("Get_Image");
        UserPhone_Intent = getArguments().getString("Get_Phone");
        UserID_Intent = getArguments().getString("Get_ID");
        FirebaseToken_Intent = getArguments().getString("Get_Token"); //Firebase Token of other person
        Room_Name_Intent = getArguments().getString("Get_Other"); // Room Name of chat
        UserLastSeen_Intent=getArguments().getString("LastSeen");
        //Sender_FCMToken = Session.getFirebaseID();
        // RECYCLER VIEW
        recyclerView = v.findViewById(R.id.Chat_Screen_Message_List);
        layoutManager = new LinearLayoutManager(getActivity());
        layoutManager.setStackFromEnd(true);
        recyclerView.setHasFixedSize(true);
        recyclerView.setLayoutManager(layoutManager);
        databaseReference = FirebaseDatabase.getInstance().getReference().child(Room_Name_Intent);
        databaseReference.addChildEventListener(this);

        adapter = new Chat_Adapter(getActivity(), message);
        recyclerView.setAdapter(adapter);
        // FETCH OLD MESSAGE FROM DATABASE
        chatDatabase();
        return v;
    }
    // FIREBASE REAL TIME DATABASE WHICH FETCH ALL MESSAGES (SYNC) FROM ONLINE DATABASE
    @Override
    public void onChildAdded(DataSnapshot dataSnapshot, String s) {
        append_chat_conversation(dataSnapshot);
    }

    @Override
    public void onChildChanged(DataSnapshot dataSnapshot, String s) {
        append_chat_conversation(dataSnapshot);
    }

    @Override
    public void onChildRemoved(DataSnapshot dataSnapshot) {

    }

    @Override
    public void onChildMoved(DataSnapshot dataSnapshot, String s) {

    }

    @Override
    public void onCancelled(DatabaseError databaseError) {

    }

    private synchronized void append_chat_conversation(DataSnapshot dataSnapshot) {
        iterator = dataSnapshot.getChildren().iterator();

        while (iterator.hasNext()) {

            // GETTING DATA FROM FIREBASE DATABASE 

            Chat_Msg = (String) ((DataSnapshot) iterator.next()).getValue();
            Chat_FROM = (String) ((DataSnapshot) iterator.next()).getValue();
            Chat_FROM_ID = (String) ((DataSnapshot) iterator.next()).getValue();
            Chat_TO = (String) ((DataSnapshot) iterator.next()).getValue();
            Chat_TimeStamp = (String) ((DataSnapshot) iterator.next()).getValue();
            Chat_Type= (String) ((DataSnapshot) iterator.next()).getValue();
            Random_ID=(String) ((DataSnapshot) iterator.next()).getValue();
            Chat_FCM_FROM= (String) ((DataSnapshot) iterator.next()).getValue();
            Chat_FCM_TO= (String) ((DataSnapshot) iterator.next()).getValue();

            Log.d(TAG, "Chat Items " + Chat_Msg + " " + Random_ID);

            Chat_Database tempChatDatabase = new Chat_Database(getActivity());
            boolean hasValue = tempChatDatabase.CheckValueExist(Random_ID);
            Log.d(TAG,"DATABASE ALREADY HAS VALUE OF TIMESTAMP= "+hasValue);

            if (!hasValue) {
                Log.d(TAG,"DATABASE DON'T HAVE SAME ENTRY FOR TIME STAMP. ENTERED INTO HAS VALUE");
                Log.d(TAG,"Chat Message "+Chat_Msg);

           if (Chat_Type.equals("Typed_Message")) {
                Log.d(TAG, "VIEW TYPE IS Message " + Chat_Msg);
                long id = chat_database.Insert_Chat(Session.getUserID(),Room_Name_Intent, UserID_Intent, "Text", Chat_Msg, Chat_FROM, Chat_TO, Chat_TimeStamp, Chat_FCM_FROM, Chat_FCM_TO, Session.getPhoneNO(), UserPhone_Intent,Random_ID,UserImage_Intent,UserLastSeen_Intent,Chat_FROM_ID);

                //Adding Chat Data Into Database
                Log.d(TAG,"Database Entry ID "+id);

                if (id == 0) {
                    Log.d(TAG,"Database Already Has Value Of This Random Id ");
                    adapter.notifyDataSetChanged();
                    continue;

                } else {
                    Log.d(TAG,"Database Don't Has Value Of This Random Id ");
                    Log.d(TAG,"Message Size "+message.size());
                    Chat_Wrapper chat_wrapper = new Chat_Wrapper(Chat_Msg, null, null, null, null, null, null, Chat_TimeStamp, UserPhone_Intent, UserImage_Intent, Chat_FROM, null,null,id);
                    message.add(chat_wrapper);
                    Log.d(TAG,"Message Size "+message.size());
                    adapter.notifyDataSetChanged();
                    Log.d(TAG,"Adapter Notified Data Set "+adapter.getItemCount());
                    recyclerView.post(new Runnable() {
                        @Override
                        public void run() {
                            Log.d(TAG, "Moving to Bottom");
                            recyclerView.smoothScrollToPosition(adapter.getItemCount());
                        }
                    });
                }
        }

        Log.d(TAG, "MESSAGE ARRAY SIZE " + message.size());
        chat_database.isDatabaseClose();
}

    private void chatDatabase(){
        //Database Init and Filling Adapter
        Log.d(TAG,"Chat Database Function");
        chat_database=new Chat_Database(getActivity());
        chatCursor=chat_database.getUserChat(UserID_Intent);
        boolean checkDB_Exist=functions.DatabaseExist(getActivity(),"CHAT_DATABASE.DB");
        boolean chatItemsCounts=chatCursor.getCount()>0;
        chatCursor.moveToFirst();
        Log.d(TAG,"Value At Chat Database "+ checkDB_Exist+" "+chatItemsCounts);
        if (checkDB_Exist && chatCursor.getCount()>0 && chatCursor.getString(chatCursor.getColumnIndex("RECEIVER_USER_ID")).equals(UserID_Intent)){

            Log.d(TAG,"Database Exist Chat Database");
            message.clear();
            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


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

            Room_Name_Intent = database_RoomName;
            layoutManager = new LinearLayoutManager(getActivity());
            recyclerView.setLayoutManager(layoutManager);
            adapter.notifyDataSetChanged();
            chatCursor.close();
            boolean value = chat_database.isDatabaseClose();
            recyclerView.post(new Runnable() {
                @Override
                public void run() {
                    Log.d(TAG, "Moving to Bottom");
                    recyclerView.smoothScrollToPosition(message.size()-1);

                }
            });
            Log.d(TAG,"Value Of Database Close or Not "+value);

        }
    }
}


推荐答案

我通过深入研究android生命周期解决了这个问题。正如我上面提到的,仅当我从通知中输入 ChatFragment 时,我才面临此问题。我只是活动状态问题。代码正在工作。

I solved this issue by digging bit into android lifecycle. As i mentioned above i am facing this issue only when i enter ChatFragment from notification. I was only activity state issue. Code was working. What i was doing i always recreate activity on notification tap ( In Firebase Code ).

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);

在挖掘了很多代码并更改了 Intent 。只有 android:launchMode = singleTask 解决了我的问题。如果不存在活动,则仅创建活动。现在,在点击通知时,它的未调用活动 onDestroy 方法。它是从 onStart 开始的活动,可以避免重新创建活动。

After digging lots of code and changing multiple flags in Intent. Only android:launchMode="singleTask" solves my issue. Which only create activity if it's not exist. Now its not calling activity onDestroy method when tapping on notification. It's start activity from onStart which avoid activity to recreate.

我将此标志添加到 AndroidManifest的 NavigationDrawer活动标签中。

I add this flag in AndroidManifest's NavigationDrawer activity tag.

 <activity
            android:name=".Navigation_Drawer"
            android:launchMode="singleTask"
            android:theme="@style/AppTheme"/>

这类问题对于开发人员来说确实令人头疼,但我不知道单行代码我可以解决这个问题。谢谢大家的帮助。

These kind of issue is really headache for developers but i don't know that with this single line of code i can solve this issue. Thanks everyone for help.

这篇关于Recyclerview适配器的notifyDataSetChanged不更新RecyclerView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆