android - 如何从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);
}
}
}
解决方案
使用 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
,因为忽略可能的错误是一种不好的做法。
推荐阅读
- c# - 将数据从一个表单传递到同一视图中另一个表单的操作方法
- javascript - JavaScript 中的“常量”范围
- ruby-on-rails - 使用定期慢速请求进行自动缩放
- selenium - Selenium - WebElement.Click(),页面刷新但不加载
- php - 如何在gmail API中的每个收件人的电子邮件正文中插入用户名或电子邮件
- laravel - Vue v-for 检索当前项目的索引
- java - 套接字超时异常后下载大文件和大zip文件
- c++ - 为什么 std::put_money() 需要美分?
- html - Spring Boot Thymeleaf 分页
- python - 将 numpy 数组转换为映射到行的值的字典