Firebase + Android - 通知 ChildAdded - 如何只获得新的孩子?

Posted

技术标签:

【中文标题】Firebase + Android - 通知 ChildAdded - 如何只获得新的孩子?【英文标题】:Firebase + Android - Notifications ChildAdded - How to get only New Childs? 【发布时间】:2014-09-03 00:36:49 【问题描述】:

我正在尝试在我的应用中设置一个 android 服务,该服务在 Firebase Ref 中侦听新的 Childs,并在发生这种情况时引发通知。

我遇到了问题,因为 addChildEventListener onChildAdded 显然会为每个现有记录调用一次,然后才会真正监听新的孩子..

在this answer@kato 中指出,如果addChildEventListenerref.endAt().limit(1).addChildEventListener(...) 一样被调用,它只会获得新添加的记录。

它实际上一次只获取一条记录(我想是limit(1)),但在侦听添加的记录之前它仍然获取一条现有记录。

这里有一些代码:

在 onCreate() 中初始化监听器:

@Override
public void onCreate() 
    super.onCreate();
    this.handler = new ChildEventListener() 
        @Override
        public void onChildAdded(DataSnapshot dataSnapshot, String s) 
            AllowedGroup ag = dataSnapshot.getValue(AllowedGroup.class);

            postNotif("Group Added!", ag.getName());
        
        ...rest of needed overrides, not used...

我使用AllowedGroup.class 来存储记录,并使用postNotif 来构建和发布通知。这部分正在按预期工作。

那么,onStartCommand()

@Override
public int onStartCommand(Intent intent, int flags, int startId) 
    this.f = new Firebase(FIREBASE_URL).child("users").child(this.currentUserUid).child("allowedGroups");
    f.endAt().limit(1).addChildEventListener(handler);
    return START_STICKY;

在实际监听新添加的子节点之前,它仍然返回一个存在的记录。

我也尝试过按时间戳查询,如下所示:

@Override
public int onStartCommand(Intent intent, int flags, int startId) 
    this.f = new Firebase(FIREBASE_URL).child("users").child(this.currentUserUid).child("allowedGroups");
    f.startAt(System.currentTimeMillis()).addChildEventListener(handler);
    return START_STICKY;

希望它只会在服务启动后获取记录集。它不获取现有记录,但甚至不获取新添加的子项

编辑:

我也想过先把所有存在的记录都存入内存,如果onChildAdded带来的记录在之前收集的列表中不存在,则有条件地发布通知,但这似乎有点矫枉过正,并认为这可能是一种更简单(对 API 更友好)的方式,对吗?

谁能提供一些关于这方面的见解?我在官方文档或任何 *** 问题或教程中都找不到任何内容。

谢谢。

【问题讨论】:

How to retreive only new data?的可能重复 firebaseRef.on('child_added', function(childSnapshot, prevChildName) // code to handle new child. ); 呢? 您是否尝试过在服务中生成一个新线程,然后添加监听器?您是否尝试过按组中的 modifiedOn 字段排序? 你找到解决这个问题的方法了吗? 您可以使用 firebase 的默认键存储您的值(使用 push() 方法)。 firebase 自动生成的每个键都放置在列表的底部,因此在添加的子项被触发后,只需检查列表中的最终值,它将是您的新数据。 【参考方案1】:

如果您有一个字段 modifiedOn,您可以索引它并设置如下查询:

Query byModified = firebaseEndpoint.orderByChild("modifiedOn").startAt(lastInAppTime);

【讨论】:

【参考方案2】:

对我来说,逻辑是具有价值——例如“状态”——在决定它是真的新记录还是旧记录之前需要对其进行验证,然后我将“状态”设置为不同的值,所以我不下次不要了:

@Override
        public void onChildAdded(DataSnapshot dataSnapshot, String previousChildKey) 

                if(dataSnapshot.hasChildren()) 

                    String Id = (String) dataSnapshot.child("user_id").getValue();
                    String status = (String) dataSnapshot.child("status").getValue();

                    if (Id != null && Id.equals(storedId) && status != null && status.equals("created")) 
                        Log.d("INCOMING_REQUEST", "This is for you!");
                        sessionsRef.child(dataSnapshot.getKey()).child("status").setValue("received");
                    

                


        

【讨论】:

如果多个帐户访问此数据,一个帐户更改“状态”=>“已接收”然后其余帐户无法再获取这些数据会发生什么。【参考方案3】:

我通过将 Firebase 数据库引用节点的项目保存在列表中来克服这个问题;并且每当触发onChildAdded(...) 方法时,检查传入的数据快照是否在您的列表中;如果不是,那就是新数据

为了达到这个目的,你必须满足以下条件:

    具有唯一值,不能在项目之间重复。 (当您使用 .push() 方法将项目添加到 Firebase 时,可以轻松实现这一点。 覆盖模型类的.equals() 方法,以完成基于此唯一值的比较。

此处根据您的输入编写 sn-ps 代码

模型类

public class AllowedGroup 

    private String id;
    public static List<AllowedGroup> sGroups;

    // reset of fields ...


    public AllowedGroup() 
    

    public String getId() 
        return id;
    

    public void setId(String id) 
        this.id = id;
    


    @Override
    public boolean equals(@Nullable Object o) 

        // If the object is compared with itself then return true
        if (o == this) 
            return true;
        

        // Check if o is an instance of AllowedGroup or not
        if (!(o instanceof AllowedGroup)) 
            return false;
        

        // typecast o to AllowedGroup so that we can compare data members
        AllowedGroup group = (AllowedGroup) o;

        // Compare data based on the unique id
        return (group.id).equals(id);
    


监听 firebase 添加的节点

@Override
public void onCreate() 
    super.onCreate();
    this.handler = new ChildEventListener() 
        @Override
        public void onChildAdded(@NonNull DataSnapshot dataSnapshot, @Nullable String s) 

            AllowedGroup group = dataSnapshot.getValue(AllowedGroup.class);

            if (!AllowedGroup.sGroups.contains(group)) 
                // Here you'll receive only the new added values
            

        

        // ...rest of needed overrides, not used... 
    


【讨论】:

以上是关于Firebase + Android - 通知 ChildAdded - 如何只获得新的孩子?的主要内容,如果未能解决你的问题,请参考以下文章

Android 中的 Firebase 通知 (Kotlin)

适用于 Android 的 Firebase 推送通知

Android - 所有 Android 版本都可以接收 Firebase 推送通知吗

自定义 Firebase 推送通知未显示 Android 通知徽章点

接收来自两个 Firebase 项目的一个 Android 应用的推送通知

Firebase 使用 Node Js 功能通知未在 android 中接收,但它直接从 firebase 面板工作