【问题标题】:Android - Firebase onChildAdded how to listen for all childAndroid - Firebase onChild 添加了如何监听所有孩子
【发布时间】:2017-07-10 12:41:04
【问题描述】:

我在显示新添加的数据时遇到问题。我的onChildAdded 正在收听任何新通知。此新通知将保存到 Firebase。我的通知包含 2 个孩子(消息和日期)。

但是,当我添加新通知时,我只能显示其中一个孩子(日期)。如果我重新运行应用程序,我可以检索所有内容,但我希望在我使用应用程序本身时进行更改。添加新通知时如何显示所有内容?是因为 onChildAdded 只听前一个孩子吗?如果需要,我可以发布我的适配器和 getter/setter 代码。

示例:我发送了 2 个新通知,而侦听器仅读取日期。截图如下。

没有顺序。它不显示新添加的通知“消息”。我添加了“Hi2”和“Hi3”。

NotificationFragment.java

public class NotificationFragment extends Fragment {

    private void prepareNotification1() {
        FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
        String userID = user.getUid();

//        mRef.child("customers").child(userID).child("Notification").addListenerForSingleValueEvent(new ValueEventListener() {
//            @Override
//            public void onDataChange(DataSnapshot dataSnapshot) {
//                for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
//                    System.out.println(postSnapshot.getValue());
//                    Notification menu = postSnapshot.getValue(Notification.class);
////                    Notification menu = new Notification(postSnapshot.getValue(String.class));
//                    notificationList.add(menu);
//                }
//                mAdapter.notifyDataSetChanged();
//            }
//
//            @Override
//            public void onCancelled(DatabaseError databaseError) {
//
//            }
//
//        });
//


        mRef.child("customers").child(userID).child("Notification").addChildEventListener(new ChildEventListener() {
            @Override
            public void onChildAdded(DataSnapshot dataSnapshot, String s) {
                    Log.d("child", "onChildAdded:" + dataSnapshot.getKey());
                    Log.d("child", "onChildAdded:" + dataSnapshot.getValue());
                    Notification menu = dataSnapshot.getValue(Notification.class);
                mAdapter.notifyDataSetChanged();
            }
        });
    }
}

FirebaseMessaging

public class MyFirebaseMessagingService extends FirebaseMessagingService {
    private DatabaseReference mRef;

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        final String uniqueID = UUID.randomUUID().toString();

        mRef.child("customers").child(userID).child("Notification").child(uniqueID).child("Date").setValue(notificationTime);
        mRef.child("customers").child(userID).child("Notification").child(uniqueID).child("Message").setValue(remoteMessage.getData().get("body"));
        createNotification(remoteMessage.getData().get("title"),remoteMessage.getData().get("body"));
}

Notification.java

public class Notification {
    private String Message;
    private String Date;


    public Notification(){
    }

    public Notification(String Message, String Date){
        this.Message = Message;
        this.Date = Date;
    }

    public String getDate() {
        return Date;
    }

    public void setDate(String Date) {
        this.Date = Date;
    }

    public String getMessage() {
        return Message;
    }

    public void setMessage(String Message) {
        this.Message = Message;
    }
}

NotificationAdapter.java

public class NotificationAdapter extends RecyclerView.Adapter<NotificationAdapter.NotificationHolder> {
    private List<Notification> notificationList;
    private Context mContext;

    public NotificationAdapter(Context mContext, List<Notification> notificationList) {
        this.mContext = mContext;
        this.notificationList = notificationList;
    }


    @Override
    public NotificationHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View inflatedView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.list_item_notification, parent, false);
        return new NotificationHolder(inflatedView);
    }

    @Override
    public void onBindViewHolder(final NotificationHolder holder, int position) {
        Notification notification = notificationList.get(position);
        holder.body.setText(notification.getMessage());
        holder.time.setText(notification.getDate());
    }

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

    public class NotificationHolder extends RecyclerView.ViewHolder {
        public TextView body;
        public TextView time;

        public NotificationHolder(View view) {
            super(view);
            body = (TextView) view.findViewById(R.id.bodyMsg);
            time = (TextView) view.findViewById(R.id.time);
        }
    }
}

【问题讨论】:

  • 你能发布你的通知类代码吗?
  • @LucaRossi 我已经发布了所有代码。
  • 当你得到Notification menu = dataSnapshot.getValue(Notification.class);中的数据时Message字段是空的?
  • @LucaRossi 不是空的。当我重新运行应用程序时,我能够检索它。但是,我想要的是当我在应用程序上时能够在“listView”上更新它,而不是关闭并再次启动。是不是因为 'onChildListener' 只读取了孩子最后的变化?

标签: java android firebase firebase-realtime-database


【解决方案1】:

我想我发现了问题,onChildAdded 仅在将孩子添加到列表时才会被触发,因此当您第一次从远程读取它们或将新通知添加到在线列表时。

在这部分代码中,您首先添加仅设置了Date 字段的通知对象,然后编辑其Message

mRef.child("customers").child(userID).child("Notification").child(uniqueID).child("Date").setValue(notificationTime);
mRef.child("customers").child(userID).child("Notification").child(uniqueID).child("Message").setValue(remoteMessage.getData().get("body"));

这就是为什么当onChildAdded 被触发时,您只能看到Date 字段,如果您还覆盖onChildChanged,您将看到Message

要解决您的问题,您应该像 here 解释的那样将整个对象添加到 firebase

这应该是结果,遵循文档

Notification newNotification = new Notification(notificationTime, remoteMessage.getData().get("body"))
mRef.child("customers").child(userID).child("Notification").child(uniqueID).setValue(newNotification);

【讨论】:

  • 你也可以避免自己生成唯一的key,你可以使用mRef.child("customers").child(userID).child("Notification").push().getKey();获取firebase生成的一个
  • 谢谢!!它解决了这个问题。是的,这就是问题所在,但我无法用技术术语正确解释。哦,我使用的是“.push”,但它为我的“日期”和“消息”生成了每个不同的键。我试图弄清楚如何将它放在同一个键中。感谢您的提示和帮助以及您的解释!我会用那个。
【解决方案2】:

您的属性名称的大小写似乎与 JSON 不匹配。具体来说:Firebase 遵循 JavaBean 约定,这意味着 getter/setter getName()/setName() 定义属性 name(带有小写的 n)。

我建议更改您的 JSON 数据以匹配此命名约定。但即使使用当前的 JSON,您也可以使用一些注释来完成工作:

public class Notification {
    private String Message;
    private String Date;


    public Notification(){
    }

    public Notification(String Message, String Date){
        this.Message = Message;
        this.Date = Date;
    }

    @PropertyName("Date")
    public String getDate() {
        return Date;
    }

    @PropertyName("Date")
    public void setDate(String Date) {
        this.Date = Date;
    }

    @PropertyName("Message")
    public String getMessage() {
        return Message;
    }

    @PropertyName("Message")
    public void setMessage(String Message) {
        this.Message = Message;
    }
}

【讨论】:

  • 感谢您的解释!但我认为问题不在于这里的命名约定。但它已经开始工作了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多