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 中指出,如果addChildEventListener
像ref.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 - 所有 Android 版本都可以接收 Firebase 推送通知吗
自定义 Firebase 推送通知未显示 Android 通知徽章点