【问题标题】:Firebase onChildChanged is fired multiple times?Firebase onChildChanged 被多次触发?
【发布时间】:2017-01-31 11:17:44
【问题描述】:

我的 recyclerview 的每个项目都有一个数量选择器。滚动时,数量值会因回收而改变。因此,我正在尝试使用最新值更新地图,并在删除或更改孩子时使用该位置通知ItemChanged。

我正在使用 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) {

        }
    });

购物车

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

【问题讨论】:

  • 是的,只要firebase的数据库发生变化,就会调用onChildChanged()方法。
  • @RishabhMahatha 我只更改了一次数据。但是方法多次触发
  • 你如何调用cartListener() 方法以及如何更改数据?我不认为到目前为止发布的代码是问题的原因。
  • @LewisMcGeary 请查看更新!
  • 如果onChildChanged() 被多次调用,很可能您多次更改了/a child。请分享minimal complete code that reproduces this problem。如果这需要您的 Cart 课程,请分享。但很可能你也可以在没有Cart 类和简单的地图的情况下重现它(如果你不能,你知道问题出在你的Cart 类:-))。

标签: android firebase firebase-realtime-database


【解决方案1】:

这是因为在每次调用 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】:

    检查你在哪里设置eventListner,如果你在某个地方使用它,它会一次又一次地调用it functionseventListner 在你的生命周期中被添加的次数。

    【讨论】:

      【解决方案3】:

      这对你有帮助

      将您的侦听器 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) {
      
              }
          });
      }
      

      【讨论】:

      • 我只需要知道更改的值,而不是整个值。所以我正在使用 ChildEventListener!
      【解决方案4】:

      这看起来像是通过将侦听器添加到节点,然后在侦听器中更新同一节点而导致循环的情况。

      在这种情况下,它是 addToCart() 方法中的 cartRef。一个ValueEventListener被添加到cartRefonDataChange中的代码然后更新cartRef下的数据,所以监听器不断地触发自己。

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

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

      【讨论】:

      • 每次两次?这看起来很不寻常,从问题中看不出是什么原因造成的,但我的第一个想法是可能多次添加同一个侦听器(即,cartListener() 方法被多次调用)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-24
      • 2016-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-13
      相关资源
      最近更新 更多