2017-04-14 61 views
0

我正在尝试使用Firebase为餐馆和酒吧创建评分系统。到目前为止,我可以阅读和编写个人评分。我遇到的问题是,为了计算特定餐厅的平均评分,我需要获得存储的评分数量和所​​有评分的总价值。目前我正在努力存储收视率。这里是我的代码onDataChange卡在无限循环中

Query RetrieveRating = databaseReference.child("ratings").child("porterhouse"); 
RetrieveRating.addValueEventListener(new ValueEventListener() { 
    @Override 
    public void onDataChange(DataSnapshot postSnapshot) { 

    //get data from snapshot 
    String data = postSnapshot.child("numRating").getValue().toString(); 

    if (!data.equals(null)) { 
     String numRating = (String) postSnapshot.child("numRating").getValue(); 

     count = Integer.valueOf(numRating); 
     count++; 

     ratingCounter = Integer.toString(count); 

     databaseReference.child("ratings").child("porterhouse").child("numRating").setValue(ratingCounter); 
    } 
    } 

    @Override 
    public void onCancelled(DatabaseError databaseError) { 

    } 
}); 

正在发生的事情是它走的是当前存储的值,加1到它,并写回数据库,但是因为每次它被存放在onDataChange()方法被调用,再次加上1,并再次形成无限循环。 我的问题是,是否有任何更改,我可以为了防止这种情况,甚至不同的方式来配置这个? 感谢

UPDATE

JSON代码如下:

{ 
     "ratings" : { 
     "porterhouse" : { 
      "numRating" : "0", 
      "totalRating" : "0" 
     } 
    } 
+0

安置自己的JSON结构 –

+0

@MartinDeSimone更新以显示的JSON代码 – EoghanBradshaw

+0

relavent一部分这将真正使基于循环因为ChildEventListener将监听该特定路径上的所有更改,并且在侦听器内部更改该路径会一次又一次触发它。 –

回答

2

使用addListenerForSingleValueEvent

RetrieveRating.addListenerForSingleValueEvent(new ValueEventListener() { 
     @Override 
     public void onDataChange(DataSnapshot postSnapshot) { 

      //get data from snapshot 
      String data = postSnapshot.child("numRating").getValue().toString(); 

      if (!data.equals(null)) { 
       String numRating = (String) postSnapshot.child("numRating").getValue(); 

       count = Integer.valueOf(numRating); 
       count++; 

       ratingCounter = Integer.toString(count); 



       databaseReference.child("ratings").child("porterhouse").child("numRating").setValue(ratingCounter); 

      } 
     } 

     @Override 
     public void onCancelled(DatabaseError databaseError) { 

     } 
    }); 

而且你应该使用火力交易递增计数器

+0

谢谢Martin,工作完美。非常感谢您的帮助 – EoghanBradshaw

2

虽然马丁的回答解决了infini te循环,它会在您的方法中留下问题。如果两个用户几乎同时对餐厅评分,他们的变化可能会相互干扰。

为了解决这个问题,马丁说,你应该use a transaction

DatabaseReference ratingRef = databaseReference.child("ratings/porterhouse/numRating"); 
postRef.runTransaction(new Transaction.Handler() { 
    @Override 
    public Transaction.Result doTransaction(MutableData mutableData) { 
     int count; 
     try { 
      count = Integer.parseInt(mutableData.getValue(String.class)); 
     } catch (NumberFormatException e) { 
      count = 0; 
     } 
     count++; 
     mutableData.setValue(Integer.toString(count)); 
     return Transaction.success(mutableData); 
    } 

    @Override 
    public void onComplete(DatabaseError databaseError, boolean b, 
          DataSnapshot dataSnapshot) { 
     Log.d(TAG, "countTransaction:onComplete:" + databaseError); 
    } 
}); 

我真的不知道为什么要存储的计数器为字符串。我会强烈建议把它作为一个数字,在这种情况下,该代码变得简单了很多:

DatabaseReference ratingRef = databaseReference.child("ratings/porterhouse/numRating"); 
postRef.runTransaction(new Transaction.Handler() { 
    @Override 
    public Transaction.Result doTransaction(MutableData mutableData) { 
     Integer count = Integer.parseInt(mutableData.getValue(Integer.class)); 
     if (count == null) count = 0; 
     count++; 
     mutableData.setValue(count); 
     return Transaction.success(mutableData); 
    } 

    @Override 
    public void onComplete(DatabaseError databaseError, boolean b, 
          DataSnapshot dataSnapshot) { 
     Log.d(TAG, "countTransaction:onComplete:" + databaseError); 
    } 
});