java - 如何从 RecyclerView 中实时删除条目

标签 java android firebase firebase-realtime-database

我正在尝试创建聊天。然而,我面临着一个大问题。当我从聊天 recyclerView 中删除条目时,该条目保留在那里,但会按预期从 firebase 数据库中删除(我的意思是只有从数据库中删除才有效)。仅当我关闭 Activity 并再次打开它时,它才会消失。我的 recyclerView 具有每次用户滚动时加载 10 个以上条目的功能。

我不明白如何从 recyclerView 中删除该条目?

我需要调用函数loadMoreMessages()吗?刷新 Activity ?

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

                                        }

                                    }
                                });
                            }
                        });

                    }

                }
            });

        }

    }


}


``

最佳答案

您正在使用ChildEventListener在你的messageQuery ,它有以下主要方法:

  • onChildAdded ,最初为每个与 messageQuery 匹配的子节点调用它查询,随后当任何子节点添加到落入 messageQuery 的数据库中时.
  • onChildRemoved ,当从数据库中删除任何(掉落的)子节点(或至少删除 messageQuery 正在监听的部分)时,会调用该函数。
  • onChildChanged ,当任何子节点 messageQuery 时调用它is Listening 已在数据库中修改。

如果我看看你的实现,你只实现了 onChildAdded 。因此,当您从数据库中删除子节点时,Firebase 会告诉您 ChildEventListener关于它,但那什么也没做。

要在消息从数据库中删除时从 UI 中删除该消息,您需要实现:

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

关于java - 如何从 RecyclerView 中实时删除条目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56436092/

相关文章:

firebase - 迁移 Flutter 应用 : realtime db to firestore

ios - 在 Swift 上从 Firebase 通过 URL 下载图像时横向加载

swift - 出现错误 : Cannot call value of non-function type 'NSURL' 的问题

java - 无法按照 Javadoc 中的描述使用 @JsonCreator 正确反序列化 JSON

android - 在 Android 中使用外部声音推送通知

java - 返回主 Activity 后调用 Activity ?

android - Eclipse 没有 java 文档来显示有关类和方法的信息。如何附加那些? +安卓

Java Socket 卡在 new ObjectInputStream() 处

java - 如何使用 Java 删除地址簿程序中的条目?

java - 如何启动OSGI-INF蓝图