2017-04-14 56 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); 
    } 
});