Как удалить запись из RecyclerView в режиме реального времени - PullRequest
0 голосов
/ 04 июня 2019

Я пытаюсь создать чат. Тем не менее, я сталкиваюсь с большой проблемой. Когда я удаляю запись из чата recyclerView, запись остается там, но удаляется из базы данных Firebase, как и ожидалось (я имею в виду, что удаление только из базы данных работает). Он исчезает только тогда, когда я закрываю действие и открываю его снова. Функция My recyclerView позволяет загружать еще 10 записей каждый раз, когда пользователь выполняет прокрутку.

Я не понимаю, как я могу удалить запись из recyclerView?

Мне нужно вызвать функцию loadMoreMessages ()? Обновить активность?

MessageAdapter.java

public class MessageAdapter extends RecyclerView.Adapter<MessageAdapter.MessageViewHolder>{


    public class MessageViewHolder extends RecyclerView.ViewHolder {

        public TextView messageText, displayName;
        public CircleImageView profileImage;
        public ImageView messageImage;


        public MessageViewHolder(View itemView) {
            super(itemView);

            messageText = (TextView) itemView.findViewById(R.id.message_text_layout);
            profileImage = (CircleImageView) itemView.findViewById(R.id.message_profile_layout);
            displayName = (TextView) itemView.findViewById(R.id.name_text_layout);
            messageImage = (ImageView) itemView.findViewById(R.id.message_image_layout);
        }
    }


    private List<Messages> mMessageList;
    private FirebaseAuth mAuth;
    private DatabaseReference mUserDatabase;
    private DatabaseReference mUserDatabaseSettings;
    private String rul, fromUser_t;
    private UserAccountSettings mUserAccountSettings;

    public MessageAdapter(List<Messages> mMessageList) {
        this.mMessageList = mMessageList;
    }

    @Override
    public MessageViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.message_single_layout,parent,false);

        mAuth = FirebaseAuth.getInstance();

        return new MessageViewHolder(v);
    }

    @Override
    public void onBindViewHolder(final MessageViewHolder holder, final int position) {


        final String current_user_id = mAuth.getCurrentUser().getUid();
        final Messages c = mMessageList.get(position);
        final String from_user = c.getFrom();
        final String message_type = c.getType();
        final String messageContent = c.getMessage();


        /**
         * popup for text message
         */

        // check if the message is from the current user
        if(from_user.equals(current_user_id))
        {
            holder.messageText.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {


                    //popup menu to select option
                    CharSequence options[] = new CharSequence[]
                            {
                                    "Delete from my phone",
                                    "Delete for Everyone" ,
                                    "Cancel"
                            };

                    final AlertDialog.Builder builder = new AlertDialog.Builder(view.getContext());

                    builder.setTitle("Message Options");
                    builder.setItems(options, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialogInterface, int i) {

                            //Click Event for each item.
                            if(i == 0)
                            {
                                deleteSentMessage(position, holder);
                               // Intent intent = new Intent(holder.itemView.getContext(), ChatActivity.class);
                              //  holder.itemView.getContext().startActivity(intent);
                                //MessageViewHolder.class.notify();
                                holder.messageText.setPaintFlags(holder.messageText.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
                            }

                            else if(i == 1)
                            {
                                deleteMessageForEveryOne(position, holder);
                              //  Intent intent = new Intent(holder.itemView.getContext(), ChatActivity.class);
                              //  holder.itemView.getContext().startActivity(intent);
                                //notifyDataSetChanged();
                                //holder.messageText.setVisibility(View.GONE);

                            }
                        }
                    });

                    builder.show();

                }
            });



        }else
        {
            // similar code to check if the message is from the other user
        }



        holder.messageText.setVisibility(View.GONE);
        holder.messageImage.setVisibility(View.GONE);

        if("text".equals(message_type))
        {
            holder.messageText.setVisibility(View.VISIBLE);
        if(from_user.equals(current_user_id))
        {
            holder.messageText.setBackgroundResource(R.drawable.message_text_background);
            holder.messageText.setTextColor(Color.WHITE);
            //todo left right not working
            holder.messageText.setGravity(Gravity.LEFT);
        }else 
        {
            holder.messageText.setBackgroundColor(Color.WHITE);
            holder.messageText.setTextColor(Color.BLACK);
            holder.messageText.setGravity(Gravity.RIGHT);
        }
        holder.messageText.setText(c.getMessage());
        }else 
        {
            holder.messageImage.setVisibility(View.VISIBLE);
            UniversalImageLoader.setImage(messageContent,holder.messageImage,null,"");
        }


    }

    @Override
    public int getItemCount() {
        return mMessageList.size();
    }



    /**
    function to Delete from my phone
    **/

    private void deleteSentMessage(final int position, final MessageViewHolder holder)
    {
        DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
        rootRef.child("messages")
                .child(mMessageList.get(position).getFrom())
                .child(mMessageList.get(position).getTo())
                .child(mMessageList.get(position).getMessageID())
                .removeValue().addOnCompleteListener(new OnCompleteListener<Void>() {
            @Override
            public void onComplete(@NonNull Task<Void> task)
            {
                if(task.isSuccessful())
                {
                    Toast.makeText(holder.itemView.getContext(), "Deleted Successfully.", Toast.LENGTH_SHORT).show();
                }else
                {
                    Toast.makeText(holder.itemView.getContext(), "Error Occurred.", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }



    /**
    function to Delete from receiver phone
    **/
    private void deleteReceiveMessage(final int position, final MessageViewHolder holder)
    {
        DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
        rootRef.child("messages")
                .child(mMessageList.get(position).getTo())
                .child(mMessageList.get(position).getFrom())
                .child(mMessageList.get(position).getMessageID())
                .removeValue().addOnCompleteListener(new OnCompleteListener<Void>() {
            @Override
            public void onComplete(@NonNull Task<Void> task)
            {
                if(task.isSuccessful())
                {
                    Toast.makeText(holder.itemView.getContext(), "Deleted Successfully.", Toast.LENGTH_SHORT).show();
                }else
                {
                    Toast.makeText(holder.itemView.getContext(), "Error Occurred.", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }


    /**
    function to Delete from both sides
    **/
    private void deleteMessageForEveryOne(final int position, final MessageViewHolder holder)
    {
        final DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
        rootRef.child("messages")
                .child(mMessageList.get(position).getTo())
                .child(mMessageList.get(position).getFrom())
                .child(mMessageList.get(position).getMessageID())
                .removeValue().addOnCompleteListener(new OnCompleteListener<Void>() {
            @Override
            public void onComplete(@NonNull Task<Void> task)
            {
                if(task.isSuccessful())
                {
                    rootRef.child("messages")
                            .child(mMessageList.get(position).getFrom())
                            .child(mMessageList.get(position).getTo())
                            .child(mMessageList.get(position).getMessageID())
                            .removeValue().addOnCompleteListener(new OnCompleteListener<Void>() {
                        @Override
                        public void onComplete(@NonNull Task<Void> task) {
                            if(task.isSuccessful())
                            {
                                Toast.makeText(holder.itemView.getContext(), "Deleted Successfully.", Toast.LENGTH_SHORT).show();
                            }
                        }
                    });
                }else
                {
                    Toast.makeText(holder.itemView.getContext(), "Error Occurred.", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }



}

ChatActivity.java



public class ChatActivity extends AppCompatActivity {

    private static final String TAG = "ChatActivity";

    //todo check is user is logedin
    //user with whom Iam talking to
    private String mChatUser;
    private Toolbar mChatToolbar;

    private DatabaseReference mRootRef;

    private TextView mTitleView, mLastSeenView;
    private CircleImageView mProfileImage;
    private FirebaseAuth mAuth;
    private String mCurrentUserId;

    private ImageButton mChatAddBtn;
    private ImageButton mChatSendBtn;
    private EditText mChatMessageView;
    private RecyclerView mMessagesList;
    private SwipeRefreshLayout mRefreshLayout;
    private final List<Messages> messagesList = new ArrayList<>();
    private LinearLayoutManager mLinearLayout;
    private MessageAdapter mAdapter;

    private static final int TOTAL_ITEMS_TO_LOAD = 10;
    private int mCurrentPage = 1;

    private int itemPos =0;
    private String mLastKey = "";
    private String mPrevKey = "";

    private static final int GALLERY_PICK = 1;

    //Storage Firebase
    private StorageReference mImageStorage;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_chat);

        // create a toolbar and set the title as the user with we are chatting to
        mChatToolbar = (Toolbar) findViewById(R.id.chat_app_bar);
        setSupportActionBar(mChatToolbar);

        ActionBar actionBar = getSupportActionBar();

        actionBar.setDisplayHomeAsUpEnabled(true);
        // to add a custom view to the toolbar
        actionBar.setDisplayShowCustomEnabled(true);

        mRootRef = FirebaseDatabase.getInstance().getReference();
        mAuth = FirebaseAuth.getInstance();
        mCurrentUserId = mAuth.getCurrentUser().getUid();

        mChatUser = getIntent().getStringExtra("user_id");
        String userName = getIntent().getStringExtra("user_name");
        getSupportActionBar().setTitle(userName);

       // String userName = getIntent().getStringExtra("user_name");

        LayoutInflater inflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View action_bar_view = inflater.inflate(R.layout.chat_custom_bar, null);

        actionBar.setCustomView(action_bar_view);

        // ---------- Custom Action bar items ---

        mTitleView = (TextView) findViewById(R.id.custom_bar_title);
        mLastSeenView = (TextView) findViewById(R.id.custom_bar_seen);
        mProfileImage = (CircleImageView) findViewById(R.id.custom_bar_image);

        mChatAddBtn = (ImageButton) findViewById(R.id.chat_add_btn);
        mChatSendBtn = (ImageButton) findViewById(R.id.chat_send_btn);
        mChatMessageView = (EditText) findViewById(R.id.chat_message_view);

        mAdapter = new MessageAdapter(messagesList);
        mImageStorage=  FirebaseStorage.getInstance().getReference();
        mMessagesList = (RecyclerView) findViewById(R.id.messages_list);
        mRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.message_swipe_layout);
        mLinearLayout = new LinearLayoutManager(this);

        mMessagesList.setHasFixedSize(true);
        mMessagesList.setLayoutManager(mLinearLayout);

        //mMessagesList.setItemViewCacheSize(25);
        mMessagesList.setDrawingCacheEnabled(true);
        mMessagesList.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);

        mMessagesList.setAdapter(mAdapter);

        loadMessages();


        mTitleView.setText(userName);
        mRootRef.child("users").child(mChatUser).addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                String online = dataSnapshot.child("lastSeen").getValue().toString();
                //String image = dataSnapshot.child()

                if(online.equals("true")){
                    mLastSeenView.setText("Online");
                }else {

                    GetTimeAgo getTimeAgo = new GetTimeAgo();

                    long lastTime = Long.parseLong(online);
                    String lastSeenTime = getTimeAgo.getTimeAgo(lastTime, getApplicationContext());
                    mLastSeenView.setText(lastSeenTime);
                }
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });


        mRootRef.child("Chat").child(mCurrentUserId).addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {

                if(!dataSnapshot.hasChild(mChatUser)){

                    Map chatAddMap = new HashMap();
                    chatAddMap.put("seen", false);
                    chatAddMap.put("timestamp", ServerValue.TIMESTAMP);

                    Map chatUserMap = new HashMap();
                    chatUserMap.put("Chat/" + mCurrentUserId + "/" + mChatUser, chatAddMap); //add map to current user
                    chatUserMap.put("Chat/" + mChatUser + "/" + mCurrentUserId, chatAddMap);

                    mRootRef.updateChildren(chatUserMap, new DatabaseReference.CompletionListener() {
                        @Override
                        public void onComplete(@Nullable DatabaseError databaseError, @NonNull DatabaseReference databaseReference) {

                            if(databaseError != null){

                                //Log.d(TAG, "onComplete: CHAT LOG", databaseError.getMessage());
                                Log.e(TAG, "onComplete: CHAT_LOG" + databaseError.getMessage().toString());
                            }
                        }
                    });
                }
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });


        mChatSendBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                sendMessage();
            }
        });



        // open gallery to get an image
        mChatAddBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent galleryIntent = new Intent();
                galleryIntent.setType("image/*");
                galleryIntent.setAction(Intent.ACTION_GET_CONTENT);

                startActivityForResult(Intent.createChooser(galleryIntent,"SELECT IMAGE"), GALLERY_PICK);
            }
        });


        //pagination
        mRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                mCurrentPage++;

                // each time it loads a new page should go to position zero
                itemPos = 0;
                loadMoreMessages();
            }
        });


    }

    /**
     * load more messages everytime uesr refreshes
     */

    private void loadMoreMessages() {

        DatabaseReference messageRef = mRootRef.child("messages").child(mCurrentUserId).child(mChatUser);
        Query messageQuery = messageRef.orderByKey().endAt(mLastKey).limitToLast(10);

        messageQuery.addChildEventListener(new ChildEventListener() {
            @Override
            public void onChildAdded(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {

                Messages message = dataSnapshot.getValue(Messages.class);
                String messageKey = dataSnapshot.getKey();

                if(!mPrevKey.equals(messageKey)){
                    messagesList.add(itemPos++, message);
                    Log.d(TAG, "onChildAdded: xx" + mPrevKey + "---" + mLastKey);

                } else {
                    mPrevKey = mLastKey;
                }


                if(itemPos == 1){

                    mLastKey = messageKey;
                }




                Log.d(TAG, "onChildAdded: TOTALKEUS" + "lastkey: " + mLastKey + " | Prev key : " + mPrevKey + " | Message Key : " + messageKey);

                mAdapter.notifyDataSetChanged();
                mRefreshLayout.setRefreshing(false);

                mLinearLayout.scrollToPositionWithOffset(itemPos , 0);

            }

            @Override
            public void onChildChanged(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {

            }

            @Override
            public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) {

            }

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

            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });


    }

    /**
     * method used to load messages once
     */

    private void loadMessages() {

        //query to get pagination and last 10 messages
        DatabaseReference messageRef = mRootRef.child("messages").child(mCurrentUserId).child(mChatUser);
        Query messageQuery = messageRef.limitToLast(mCurrentPage * TOTAL_ITEMS_TO_LOAD);


        messageQuery.addChildEventListener(new ChildEventListener() {
            @Override
            public void onChildAdded(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {

                Messages message = dataSnapshot.getValue(Messages.class);

                itemPos++;

                if(itemPos == 1){
                    // get the key to be user as a start point when loading more items
                    String messageKey = dataSnapshot.getKey();
                    mLastKey = messageKey;
                    mPrevKey = messageKey;

                    Log.d(TAG, "onChildAdded: last " +mLastKey + "  prev  " + mPrevKey + "  messa  " + messageKey + "-----------");
                }

                messagesList.add(message);
                mAdapter.notifyDataSetChanged();

                //pagination - define the bottom of the recycler view
                //automatic scroll to bottom
                mMessagesList.scrollToPosition(messagesList.size() - 1);

                mRefreshLayout.setRefreshing(false);
            }

            @Override
            public void onChildChanged(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {

            }

            @Override
            public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) {

            }

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

            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });

    }


    /**
     * send photo message
     * @param requestCode
     * @param resultCode
     * @param data
     */


    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if(requestCode == GALLERY_PICK && resultCode == RESULT_OK){

            Uri imageUri = data.getData();

            final String current_user_ref = "messages/" + mCurrentUserId + "/" + mChatUser;
            final String chat_user_ref = "messages/" + mChatUser + "/" + mCurrentUserId;

            DatabaseReference user_message_push = mRootRef.child("messages")
                    .child(mCurrentUserId).child(mChatUser).push();

            final String push_id = user_message_push.getKey();


            StorageReference filepath = mImageStorage.child("message_images").child( push_id + ".jpg");

            filepath.putFile(imageUri).addOnCompleteListener(new OnCompleteListener<UploadTask.TaskSnapshot>() {
                @Override
                public void onComplete(@NonNull Task<UploadTask.TaskSnapshot> task) {

                    if(task.isSuccessful()){

                        Task<Uri> result = task.getResult().getMetadata().getReference().getDownloadUrl();
                        result.addOnSuccessListener(new OnSuccessListener<Uri>() {
                            @Override
                            public void onSuccess(Uri uri) {
                                String download_url = uri.toString();

                                Map messageMap = new HashMap();
                                messageMap.put("message", download_url);
                                messageMap.put("seen", false);
                                messageMap.put("type", "image");
                                messageMap.put("time", ServerValue.TIMESTAMP);
                                messageMap.put("from", mCurrentUserId);
                                messageMap.put("to", mChatUser);
                                messageMap.put("messageID", push_id );

                                Map messageUserMap = new HashMap();
                                messageUserMap.put(current_user_ref + "/" + push_id, messageMap);
                                messageUserMap.put(chat_user_ref + "/" + push_id, messageMap);

                                mChatMessageView.setText("");

                                mRootRef.updateChildren(messageUserMap, new DatabaseReference.CompletionListener() {
                                    @Override
                                    public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {

                                        if(databaseError != null){

                                            Log.d("CHAT_LOG", databaseError.getMessage().toString());

                                        }

                                    }
                                });
                            }
                        });

                    }

                }
            });

        }

    }


}


``

Ответы [ 2 ]

1 голос
/ 04 июня 2019

Вы используете ChildEventListener в вашем messageQuery, который имеет следующие основные методы:

  • onChildAdded, который вызывается первоначально для каждого дочернего узла, соответствующего вашему запросу messageQuery, а затем, когда любой дочерний узел добавляется в базу данных, которая попадает в messageQuery.
  • onChildRemoved, который вызывается, когда любой дочерний узел (который падает) удаляется из базы данных (или, по крайней мере, той части, которую messageQuery прослушивает).
  • onChildChanged, который вызывается, когда любой дочерний узел, который прослушивает messageQuery, изменяется в базе данных.

Если я посмотрю на вашу реализацию, вы реализовали только onChildAdded. Поэтому, когда вы удаляете дочерний узел из базы данных, Firebase сообщает вашему ChildEventListener об этом, но тогда это ничего не делает.

Чтобы удалить сообщение из пользовательского интерфейса при его удалении из базы данных, вам необходимо реализовать:

@Override
public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) {
    // TODO: remove the message matching dataSnapshot from messagesList
    // TODO: call adapter.notifyDataSetChanged() so that the UI gets updates
}
0 голосов
/ 05 июня 2019

Спасибо, Фрэнк и Ведпракаш. Это было очевидно. В то время я не понимал, как пройти позицию и удалить элемент с помощью onChildRemoved. Теперь я понимаю. То, что я сделал, было основано на этом посте: Как использовать onChildRemoved в базе данных Firebase Realtime?

            @Override
            public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) {
                Toast.makeText(ChatActivity.this, "Entered on this part!", Toast.LENGTH_SHORT).show();

                int index = keyList.indexOf(dataSnapshot.getKey());
                messagesList.remove(index);
                keyList.remove(index);
                //mAdapter.notifyDataSetChanged();
                mAdapter.notifyItemRemoved(index);
            }

Я проверил это и работает нормально. Тем не менее, у него есть небольшая проблема. Мой чат загружает 10 элементов (определяется как: private static final int TOTAL_ITEMS_TO_LOAD = 10; ). Если пользователь выполнит прокрутку, он загрузит больше элементов.

Когда я открываю страницу чата, загружаются элементы от «2» до «11», но когда я удаляю элемент, например, «9», появляется элемент «1». Это означает, что элемент прямо перед нулевой позицией messagesList будет отображаться.

Я пробовал несколько вещей. Моя последняя попытка была установлена ​​mLinearLayout.scrollToPosition, уменьшите TOTAL_ITEMS_TO_LOAD. И проблема остается в живых. (

Перед удалением

enter image description here

После удаления элемента

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...