Arnav Vohra Arnav Vohra - 22 days ago 6
Android Question

Understanding Firebase ValueEventListeners onDataChange()

So I went through the documentation about how to retrieve datain Firebase: https://firebase.google.com/docs/database/android/retrieve-data

In my firebase app I am retrieving the values using the addListenerForSingleValueEvent.
Those values retrieved(here userIdKey) in the onDataChange method are used to make updates to some other places in the database.

What I have observed is that sometimes the updates are made everywhere except
at 123 (refer the code below).

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) {
}
});


How to solve this issue.

Also can someone elabrate on how onDataChange works , does it get called when all the values at the node are retrieved or 'some' of the data is retrieved ?

Should one use AsyncTask in such a scenario when retrieving data.

Answer Source

Your code seems to delete fanned out data from many locations.

When you perform a multi-location update() such as this, the security rules for all nodes are checked before any of the changes are made. So (unless there is a bug in the way Firebase enforces these specific security rules), the disconnect can't be caused by security rules.

If your other nodes are updated, but /user-subscriptions/" + userIdKey + "//" + mChannelKey is not deleted, then you are likely not getting any children in dataSnapshot (and thus not passing them in delChannelMap). You'll want to run through the code in a debugger to verify that.

Whenever troubleshooting issues such as this, be sure to handle onCancelled(). It is the easiest way to get an indication of why an operation failed. Although I don't think it will execute here (after all, the write operation seems to succeed), I recommend you attach a completion callback to setValue:

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

Throwing an exception like this ensures that it will be very difficult to overlook such an error next time.