首页 > 解决方案 > 如何从firebase实时数据库更新recyclerview以用于聊天应用

问题描述

我正在同时使用 recyclerview 和 firebase 实时数据库,以允许用户向其他用户发送消息。发送消息时,我需要再次启动该活动以重新加载更新。无论如何,是否可以自动执行此操作,以便当用户单击时发送消息直接显示。

单击发送按钮时的操作


 sendButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {


                String message = messageBox.getText().toString();
                if (message.equals("")){
                    Toast.makeText(privatemessageactivity.this, "You cant send an empty message", Toast.LENGTH_SHORT).show();
                }else{


                    messagedref.addListenerForSingleValueEvent(new ValueEventListener() {
                        @Override
                        public void onDataChange(@NonNull DataSnapshot snapshot) {
                            if (!snapshot.exists()){
                                messagedref.setValue(true);
                            }
                        }

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

                        }
                    });



                    Map<String,Object> mymessage = new HashMap<>();
                    mymessage.put("Image",myImage);
                    mymessage.put("Message",message);
                    sendmessageref.push().setValue(mymessage);
                }
            }
        });


检索数据的操作


sendmessageref.addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot snapshot) {
                if (snapshot.exists()){
                    for (DataSnapshot snapshot1 : snapshot.getChildren()){
                        MessageClass ld = snapshot1.getValue(MessageClass.class);
                        list.add(ld);
                    }

                    adapter = new MessageAdapter(list);
                    recyclerView.setAdapter(adapter);
                }
            }

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

            }
        });

我的适配器类和我的 ViewHolder 类


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

        private List<MessageClass> list;

        public MessageAdapter(List<MessageClass> list) {
            this.list = list;
        }

        @NonNull
        @Override
        public MessageAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.messagelayout,parent,false);
            return new ViewHolder(view);
        }

        @Override
        public void onBindViewHolder(@NonNull MessageAdapter.ViewHolder holder, int position) {

            MessageClass ld = list.get(position);
            holder.message.setText(ld.getMessage());

            if (!ld.getImage().equals("noimage")){
                Glide.with(getApplicationContext()).load(ld.getImage()).into(holder.circleImageView);
            }else{
                Glide.with(getApplicationContext()).load(R.drawable.profile).into(holder.circleImageView);
            }

        }

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

        public class ViewHolder extends RecyclerView.ViewHolder{

            TextView message;
            CircleImageView circleImageView;

            public ViewHolder(@NonNull View itemView) {
                super(itemView);

                message = itemView.findViewById(R.id.messagesmessage);
                circleImageView = itemView.findViewById(R.id.messagespp);

            }
        }
    }

标签: androidfirebasefirebase-realtime-database

解决方案


使用 Firebase 的全部目的是您不必显式地重新加载消息。如果您使用addValueEventListener而不是addListenerForSingleValueEvent,Firebase 将继续侦听服务器上的更改,onDataChange如果有任何更改,将再次调用您。

因此,使您的消息列表保持最新的常用方法是:

adapter = new MessageAdapter(list);
recyclerView.setAdapter(adapter);

sendmessageref.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(@NonNull DataSnapshot snapshot) {
        list.clear();
        for (DataSnapshot snapshot1 : snapshot.getChildren()){
            MessageClass ld = snapshot1.getValue(MessageClass.class);
            list.add(ld);
        }
        adapter.notifyDataSetChanged();
    }

    @Override
    public void onCancelled(@NonNull DatabaseError error) {
        throw error.toException();
    }
});

变化:

  • 使用addValueEventListener代替,addListenerForSingleValueEvent以便在初始数据和发生更改时都调用它。
  • 在 之外创建和分配适配器onDataChange,因为您只想设置一次适配器,然后更新其数据。
  • 清除 中的列表onDataChange,因为我们现在会被多次调用,并且每次我们都会获得完整DataSnapshot的所有相关数据。
  • 通知适配器新数据,adapter.notifyDataSetChanged()以便它可以刷新 UI。
  • 实施onCancelled,因为忽略可能的错误是一种不好的做法。

推荐阅读