Firebase child_ added 只添加孩子

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11788902/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 16:35:27  来源:igfitidea点击:

Firebase child_added only get child added

firebase

提问by Matt Robertson

From the Firebase API:

来自 Firebase API:

Child Added: This event will be triggered once for each initial child at this location, and it will be triggered again every time a new child is added.

Child 添加:此事件会针对该位置的每个初始子项触发一次,每次添加新子项时都会再次触发。

Some code:

一些代码:

listRef.on('child_added', function(childSnapshot, prevChildName) {
    // do something with the child
});

But since the function is called once for each child at this location, is there any way to get only the child that was actually added?

但是由于该函数在这个位置每个孩子调用一次,有没有办法只获取实际添加的孩子?

采纳答案by Kato

To track things added since some checkpoint without fetching previous records, you can use endAt()and limit()to grab the last record:

要跟踪自某个检查点以来添加的内容而不获取以前的记录,您可以使用endAt()limit()获取最后一条记录:

// retrieve the last record from `ref`
ref.endAt().limitToLast(1).on('child_added', function(snapshot) {

   // all records after the last continue to invoke this function
   console.log(snapshot.name(), snapshot.val());

});

回答by tibeoh

limit()method is deprecated. limitToLast()and limitToFirst()methods replace it.

limit()方法已弃用。limitToLast()limitToFirst()方法取代它。

// retrieve the last record from `ref`
ref.limitToLast(1).on('child_added', function(snapshot) {

   // all records after the last continue to invoke this function
   console.log(snapshot.name(), snapshot.val());
   // get the last inserted key
   console.log(snapshot.key());

});

回答by smackjax

Since calling the ref.push()method without data generates path keys based on time, this is what I did:

由于调用ref.push()没有数据的方法根据时间生成路径键,这就是我所做的:

// Get your base reference
const messagesRef = firebase.database().ref().child("messages");

// Get a firebase generated key, based on current time
const startKey = messagesRef.push().key;

// 'startAt' this key, equivalent to 'start from the present second'
messagesRef.orderByKey().startAt(startKey)
.on("child_added", 
    (snapshot)=>{ /*Do something with future children*/}
);

Note that nothing is actually written to the reference(or 'key') that ref.push()returned, so there's no need to catch empty data.

请注意,实际上没有将任何内容写入返回的引用(或“键”)ref.push(),因此无需捕获空数据。

回答by Juntae

I tried other answers way but invoked at least once for last child. If you have a time key in your data, you can do this way.

我尝试了其他答案方式,但至少为最后一个孩子调用了一次。如果您的数据中有时间键,您可以这样做。

ref.orderByChild('createdAt').startAt(Date.now()).on('child_added', ...

回答by Milligator

Swift3 Solution:

Swift3 解决方案:

You can retrieve your previous data through the following code:

您可以通过以下代码检索以前的数据:

    queryRef?.observeSingleEvent(of: .value, with: { (snapshot) in
        //Your code

    })

and then observe the new data through the following code.

然后通过以下代码观察新数据。

queryRef?.queryLimited(toLast: 1).observe(.childAdded, with: { (snapshot) in

 //Your Code

        })

回答by Zain

Since .limitToLast()method still called for the last item in your list even if it's not a new item, we can solve it as below:

由于.limitToLast()方法仍然调用列表中的最后一个项目,即使它不是一个新项目,我们可以如下解决它:

The idea is:

这个想法是:

Create a List that keeps your firebase items; and whenever onChildAdded(...)method is called, check if the incoming datasnapshot is in your list or not; if not, then it's new data

创建一个列表来保存您的 Firebase 项目;每当onChildAdded(...)调用方法时,检查传入的数据快照是否在您的列表中;如果不是,那么它是新数据

In order to achieve this you must meet below conditions:

为了实现这一点,您必须满足以下条件:

  1. Have a unique value for each item. (this can be achieved when you add items into Firebase by using the key generated by .push()method.

  2. Override .equals()method of your model class in order to fulfill the comparison based on this unique value.

  1. 每个项目都有一个独特的价值。(这可以在您使用.push()方法生成的密钥将项目添加到 Firebase 时实现。

  2. 覆盖.equals()模型类的方法以完成基于此唯一值的比较。

Code snippet

代码片段

Note: I put the list of items in the model class as of my choice.

注意:我根据自己的选择将项目列表放在模型类中。

Model class

模型类

public class MyModel {

    private String id; // unique ID from model to another
    public static List<MyModel> sItems; // my tracked items

    // reset of fields ...


    public MyModel() {
    }

    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 MyModel or not
        if (!(o instanceof MyModel)) {
            return false;
        }

        // typecast o to MyModel so that we can compare data members
        MyModel model = (MyModel) o;

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

}

Firebase listener

Firebase 侦听器

private ChildEventListener mChildEventListener = new ChildEventListener() {
    @Override
    public void onChildAdded(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {

        Log.d(TAG, "ChildEventListener: onChildAdded()");

        MyModel deal = dataSnapshot.getValue(MyModel.class);
        if (!MyModel.sItems.contains(model)) {
            // Here you'll receive only the new added values
        }

    }

    @Override
    public void onChildChanged(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
        Log.d(TAG, "ChildEventListener: onChildChanged()");
    }

    @Override
    public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) {
        Log.d(TAG, "ChildEventListener: onChildRemoved()");
    }

    @Override
    public void onChildMoved(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
        Log.d(TAG, "ChildEventListener: onChildMoved()");
    }

    @Override
    public void onCancelled(@NonNull DatabaseError databaseError) {
        Log.d(TAG, "ChildEventListener: onCancelled()");
    }
};

Then limit to last

然后限制到最后

databaseReference.limitToLast(1).addChildEventListener(mChildEventListener);