firebase onChildChanged被多次触发?

时间:2017-01-31 11:17:44

标签: android firebase firebase-realtime-database

我的recyclerview的每个项目都有一个数量选择器。滚动时数量值因回收而发生变化。因此,我正在尝试使用最新值和更新来更新地图。每当移除或更改子项时,notifyItemChanged都会显示该位置。

我正在使用ChildEventListener来监听孩子的变化。但是当onChildChanged发生单个更改时,将继续打印util onDestroy。

我该如何解决这个问题?请指导我......

private void cartListener(int pos) {

        cartRef = mCustDB.child(Email).child("mycart");
        cartRef.addChildEventListener(new ChildEventListener() {
            @Override
            public void onChildAdded(DataSnapshot dataSnapshot, String s) {

            }

            @Override
            public void onChildChanged(DataSnapshot dataSnapshot, String s) {
                Timber.d("onChildChanged > " + dataSnapshot.getKey());
            }

            @Override
            public void onChildRemoved(DataSnapshot dataSnapshot) {

            }

            @Override
            public void onChildMoved(DataSnapshot dataSnapshot, String s) {

            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        });
    }

logcat的

01-31 16:34:58.759 27963-27963/? D/BrowsePresenter: onChildChanged > c02p02
01-31 16:34:58.782 27963-27963/? D/BrowsePresenter: onChildChanged > c02p02
01-31 16:34:59.399 27963-27963/? D/BrowsePresenter: onChildChanged > c02p02
01-31 16:34:59.409 27963-27963/? D/BrowsePresenter: onChildChanged > c02p02
01-31 16:35:00.055 27963-27963/? D/BrowsePresenter: onChildChanged > c02p02
01-31 16:35:01.959 27963-27963/? D/BrowsePresenter: onChildChanged > c02p02
01-31 16:35:01.970 27963-27963/? D/BrowsePresenter: onChildChanged > c02p02
01-31 16:35:02.599 27963-27963/? D/BrowsePresenter: onChildChanged > c02p02

注意

我只更改了一次数据。但是对于每次更改,方法都会不停地触发,直到我删除侦听器!

更新

问题在于addToCart方法,因为如果我直接在firebase中更新值。听众只被解雇了两次。

如果我使用以下方法更新值。它被多次触发,直到我删除监听器。

public void addToCart(Product item, int quantity, int position) {
    cartRef = mCustDB.child(Email).child("mycart");

    cartRef.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            String prodID = null;
            List<String> mKey = new ArrayList<>();
            for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
                prodID = postSnapshot.getKey();
                mKey.add(prodID);
            }
            if (!mKey.contains(item.productID())) {
                Cart mycart = new Cart(item.productID(), 1);
                cartRef.updateChildren(mycart.toMap());
                Timber.d("updateChildren >> ");
            } else {
                if (quantity == 0) {
                    Timber.d("Remove >> " + item.productID());
                    cartRef.child(item.productID()).removeValue();
                } else {
                    Timber.d("INCREASE >> " + item.productID() + quantity);
                    cartRef.child(item.productID()).setValue(quantity);
                }
            }
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });

CART

public class Cart {

    public String productID;
    public int quantity = 0;

    public Cart() {
    }

    public Cart(String productID, int quantity) {
        this.productID = productID;
        this.quantity = quantity;
    }

    public Cart(String productID) {
        this.productID = productID;
    }

    @Exclude
    public Map<String, Object> toMap() {
        HashMap<String, Object> result = new HashMap<>();
        result.put(productID , quantity);
        return result;
    }
}

4 个答案:

答案 0 :(得分:0)

如果您在某个地方一次又一次地使用它,请检查您为eventListner设置的位置,而不是将it functions的次数称为eventListner。生命周期。

答案 1 :(得分:0)

这是因为在每次调用addToCard()时都会添加一个新的侦听器,因此必须删除以前的侦听器,如下所示:

public void addToCart(Product item, int quantity, int position) {
    // Add a new propery for the listener
    if (cartRef != null && valueEventListener != null) {
        cartRef.removeEventListener(valueEventListener);
    }

    cartRef = mCustDB.child(Email).child("mycart");
    valueEventListener = new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            String prodID = null;
            List<String> mKey = new ArrayList<>();
            for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
                prodID = postSnapshot.getKey();
                mKey.add(prodID);
            }
            if (!mKey.contains(item.productID())) {
                Cart mycart = new Cart(item.productID(), 1);
                cartRef.updateChildren(mycart.toMap());
                Timber.d("updateChildren >> ");
            } else {
                if (quantity == 0) {
                    Timber.d("Remove >> " + item.productID());
                    cartRef.child(item.productID()).removeValue();
                } else {
                    Timber.d("INCREASE >> " + item.productID() + quantity);
                    cartRef.child(item.productID()).setValue(quantity);
                }
            }
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    };

    cartRef.addValueEventListener(valueEventListener);
}

答案 2 :(得分:-1)

这会对你有所帮助

将Listner ChildEventListener连接到ValueEventListener。

 cartRef = mCustDB.child(Email).child("mycart");
    cartRef.addChildEventListener(new ValueEventListener() {
       @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
           Timber.d("onChildChanged > " + dataSnapshot.getKey());
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });
}

答案 3 :(得分:-2)

这看起来像是通过向节点添加侦听器,然后在侦听器中更新同一节点来引发循环的情况。

在这种情况下,它是cartRef方法中的addToCart()ValueEventListener已添加cartRefonDataChange中的代码会更新cartRef下的数据,因此侦听器会不断触发自身。

在决定如何进行之前,您的听众似乎要检查购物车的状态;也许避免循环的最简单方法是添加一个单值事件监听器,这样你仍然可以检查,但避免循环。

cartRef.addListenerForSingleValueEvent(new ValueEventListener() {
// same listener as before
....