了解Firebase ValueEventListeners onDataChange()

时间:2016-08-21 08:38:56

标签: android firebase firebase-realtime-database

所以我浏览了有关如何检索数据Firebase的文档:https://firebase.google.com/docs/database/android/retrieve-data

在我的firebase应用程序中,我使用addListenerForSingleValueEvent检索值。 在onDataChange方法中检索的那些值(此处为 userIdKey )用于更新数据库中的其他某些位置。

我观察到的是,有时除了以外的地方都会进行更新 123 (请参阅下面的代码)。

    DatabaseReference channelFollowersRef = mDatabase.child("followers").child(mKey);
    channelFollowersRef.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {

            for(DataSnapshot childSnapshot:dataSnapshot.getChildren()){
                String userIdKey=childSnapshot.getKey();
        /*123*/ delChannelMap.put("/user-subscriptions/" + userIdKey + "//" + mChannelKey,null);
            }

            delChannelMap.put("/channels/" + mChannelKey, null);
            delChannelMap.put("/user-channels/" + getUid() + "/" + mChannelKey, null);
            delChannelMap.put("/channels-notices/" + mChannelKey, null);
            delChannelMap.put("/channels-subChannels/" + mChannelKey, null);
            delChannelMap.put("/channels-subChannels-comments/" + mChannelKey, null);
            delChannelMap.put("/channel-followers/" + mChannelKey, null);

            mDatabase.updateChildren(delChannelMap, new DatabaseReference.CompletionListener() {
                @Override
                public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
                    Toast.makeText(ChannelDetailActivity.this, "Channel is now deleted.", Toast.LENGTH_SHORT).show();
                }
            });
        }
        @Override
        public void onCancelled(DatabaseError databaseError) {
        }
    });

如何解决这个问题。

也有人可以详细说明onDataChange如何工作,当检索到节点上的所有值或检索到“某些”数据时,是否会调用它?

在检索数据时,应该在这种情况下使用AsyncTask。

2 个答案:

答案 0 :(得分:2)

    只要子节点发生更改,
  1. onDataChange一次为您提供所有基础子节点

  2. Firebase在检索数据时使用不同的线程来执行其任务,因此无需使用AsyncTask

  3. 您的代码中的问题可能是由于String userIdKey=childSnapshot.getKey(); ... childSnapshot.getKey();没有触发您想要的数据..如果数据被正确检索,您应该检查LOGCAT。

  4. 如果还不清楚,请添加数据库的Json Data,以便更容易理解正在发生的事情。

答案 1 :(得分:1)

您的代码似乎删除了许多位置的扇出数据。

执行此类多位置update()时,将在进行任何更改之前检查所有节点的安全规则。因此(除非Firebase执行这些特定安全规则的方式存在错误),安全规则不会导致断开连接。

如果您的其他节点已更新,但未删除/user-subscriptions/" + userIdKey + "//" + mChannelKey,则您可能无法在dataSnapshot中收到任何子节点(因此未在delChannelMap中传递它们)。您需要在调试器中运行代码来验证。

每当解决此类问题时,请务必处理onCancelled()。这是了解操作失败原因的最简单方法。虽然我不认为它会在这里执行(毕竟,写操作似乎成功了),我建议你attach a completion callback to setValue

ref.setValue("My new value", new DatabaseReference.CompletionListener() {
    public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
        throw databaseError.toException();
    }
});

抛出这样的异常可以确保下次很难忽略这样的错误。