我在Android中有以下方法(用Java实现):
public static void getInformationWhenInfoButtonIsPressed (FirebaseRatingCallback callback,float [] ratingValue, String item) {
DatabaseReference rootRef_Firebase;
rootRef_Firebase = FirebaseDatabase.getInstance(DataBaseEntries.FIREBASE_URL).getReference();
rootRef_Firebase
.child(DataBaseEntries.FIREBASE_NODE_RATINGS_AGGREGATED)
.orderByChild(DataBaseEntries.FIREBASE_NAME)
.equalTo(item)
.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
int numberOfRatingsOverall = 0;
double tempScoreOverall =0;
for (DataSnapshot ds: dataSnapshot.getChildren()) {
float averageRatingOfCurrentDrink = 0;
int numberOfRatingsCurrentDrink = 0;
if (ds.child(DataBaseEntries.FIREBASE_AVERAGE_RATING).getValue(Float.class)!=null) {
averageRatingOfCurrentDrink= ds.child(DataBaseEntries.FIREBASE_AVERAGE_RATING).getValue(Float.class);
}
if (ds.child(DataBaseEntries.FIREBASE_NUMBER_OF_RATINGS).getValue(Integer.class)!=null) {
numberOfRatingsCurrentDrink = ds.child(DataBaseEntries.FIREBASE_NUMBER_OF_RATINGS).getValue(Integer.class);
numberOfRatingsOverall= numberOfRatingsOverall + numberOfRatingsCurrentDrink ;
}
tempScoreOverall = tempScoreOverall + numberOfRatingsCurrentDrink * averageRatingOfCurrentDrink;
}
ratingValue[0] = (float) (tempScoreOverall/numberOfRatingsOverall);
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
throw error.toException();
}
});
ratingValue[0] = (float) (Math.round(ratingValue[0] * 10.0) / 10.0);
}
在同一个类中,我有以下接口:
public interface FirebaseRatingCallback {
void onCallBackRating (boolean dataIsReadFromFirebase); }
这个方法应该改变引用数据类型数组ratingValue[0]
的值。不幸的是Firebase实时数据库是异步工作的,所以我不得不使用回调函数,我使用FirebaseRatingCallback callback
。但是我不知道如何使用ValueEventListener
来完成这个任务,就像我在这个例子中所做的那样。我知道如何用OnCompleteListener
来做这件事,因为你有public void onComplete(@NonNull Task<Void> task) {
方法,当我有ValueEventListener
时,我不能用它。
因此,我尝试添加以下内容,但这不起作用:
public static void getInformationWhenInfoButtonIsPressed (FirebaseRatingCallback callback,float [] ratingValue, String item) {
DatabaseReference rootRef_Firebase;
rootRef_Firebase = FirebaseDatabase.getInstance(DataBaseEntries.FIREBASE_URL).getReference();
rootRef_Firebase
.child(DataBaseEntries.FIREBASE_NODE_RATINGS_AGGREGATED)
.orderByChild(DataBaseEntries.FIREBASE_NAME)
.equalTo(item)
.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
int numberOfRatingsOverall = 0;
double tempScoreOverall =0;
for (DataSnapshot ds: dataSnapshot.getChildren()) {
float averageRatingOfCurrentDrink = 0;
int numberOfRatingsCurrentDrink = 0;
if (ds.child(DataBaseEntries.FIREBASE_AVERAGE_RATING).getValue(Float.class)!=null) {
averageRatingOfCurrentDrink= ds.child(DataBaseEntries.FIREBASE_AVERAGE_RATING).getValue(Float.class);
}
if (ds.child(DataBaseEntries.FIREBASE_NUMBER_OF_RATINGS).getValue(Integer.class)!=null) {
numberOfRatingsCurrentDrink = ds.child(DataBaseEntries.FIREBASE_NUMBER_OF_RATINGS).getValue(Integer.class);
numberOfRatingsOverall= numberOfRatingsOverall + numberOfRatingsCurrentDrink ;
}
tempScoreOverall = tempScoreOverall + numberOfRatingsCurrentDrink * averageRatingOfCurrentDrink;
}
public void onComplete(@NonNull Task<Void> task) {
ratingValue[0] = (float) (tempScoreOverall/numberOfRatingsOverall);
callback.onCallBackRating(true);
}
}
@Override
public void onCancelled(@NonNull DatabaseError error) {
throw error.toException();
}
});
}
有人知道怎么做吗?
1条答案
按热度按时间vwoqyblh1#
我知道写入数据库时如何执行此操作,但不知道从数据库中读取内容时如何执行此操作。
最简单的解决方案是在查询对象上调用get(),一旦操作完成,就更新LiveData对象,然后观察UI中的变化。
来自Query #get()的文档:
执行查询并将结果作为QuerySnapshot返回。
因此,一旦查询完成,即使数据库发生更改,也不会有其他未来事件,因此在查询完成后,不会有任何东西影响您的UI。
没有LiveData是否无法做到这一点?
还有其他方法可以做到这一点,但这是迄今为止最简单的一种。不建议再使用回调。
使用LiveData时,我需要大量代码,因为我还需要2个额外的类(ViewModel和LiveData类)。
这有什么问题?这就是编程。至于ViewModel,这是Android团队推荐的构建应用程序的方式。
不要对LiveData和ViewModel做一些全新的事情,因为这也会花费太多的时间,并且会因为许多类而增加复杂性。
这不会花太多时间。只需要几分钟。一旦你理解了这些概念,你就会成为一个更好的Android开发者。不要害怕学习新东西。
P. S. Java仍然是一门很棒的语言,但是对于Android开发来说,我推荐Kotlin,你试图实现的东西可以用Kotlin用单行代码写出来。