android - 当我计算食物的平均评分时,将此值保存到显示为 0.0 的食物对象中
问题描述
在我的实时数据库(Firebase)中,我有两个“集合”,一个用于 essen(食物),一个用于 bewertung(食物评级)
我尝试在我的应用程序中显示每种食物的数据,该数据适用于食物名称和价格(Preis)
因此我计算每种食物的平均评分,该评分根据控制台中显示的值起作用
但是当我尝试访问每种食物的平均值时,将其设置为 TextView,平均值为 0.0,这是默认的浮点值。但食物的所有其他价值都正确显示(名称和价格)
这是我的片段 java 类,我在其中计算平均值并设置从 firebase 检索的所有值:
public class Aktuelle_Bewertungen_Fragment extends Fragment{
//Elemente:
private RecyclerView recyclerView_aktuelle_Bewertungen;
private View aktuelleBewertungenView;
private DatabaseReference essenRef;
private DatabaseReference bewertungenRef;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
aktuelleBewertungenView = inflater.inflate(R.layout.fragment_aktuelle_bewertungen, container, false);
//Elemente finden:
recyclerView_aktuelle_Bewertungen = (RecyclerView) aktuelleBewertungenView.findViewById(R.id.recyler_aktuelle_bewertungen);
//Referenz auf essen:
essenRef = FirebaseDatabase.getInstance().getReference().child("essen");
//Referenz auf bewertungen:
bewertungenRef = FirebaseDatabase.getInstance().getReference().child("bewertung");
return aktuelleBewertungenView;
}
@Override
public void onStart() {
super.onStart();
FirebaseRecyclerOptions options = new FirebaseRecyclerOptions.Builder<essen>().setQuery(essenRef, essen.class).build();
final FirebaseRecyclerAdapter<essen, EssenViewHolder> adapter = new FirebaseRecyclerAdapter<essen, EssenViewHolder>(options) {
@NonNull
@Override
public EssenViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.reihen, parent, false);
EssenViewHolder viewHolder = new EssenViewHolder(view);
return viewHolder;
}
@Override
protected void onBindViewHolder(@NonNull final EssenViewHolder holder, final int position, @NonNull essen model) {
final ArrayList<essen> testessen =new ArrayList<>();
essenRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot ds : dataSnapshot.getChildren()){
final essen e = new essen();
e.name = ds.child("name").getValue(String.class);
e.Preis = ds.child("Preis").getValue(String.class);
bewertungenRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
float sum = (float) 0.0;
int counter = 0;
for (DataSnapshot ds1 : dataSnapshot.getChildren()){
if (ds1.child("eid").getValue(String.class).equals(e.name)){
sum = sum + ds1.child("wert").getValue(float.class);
counter ++;
}
}
float durchschnitt = sum/counter;
Log.i("durchschnitt" , " " + sum + " "+ counter + " " +durchschnitt);
e.setAverage(durchschnitt);
Log.i("essen wert: " , " " + e.getAverage());
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
testessen.add(e);
}
holder.essenName.setText(testessen.get(position).getName());
holder.essenPreis.setText(testessen.get(position).getPreis());
float test = (float) testessen.get(position).getAverage();
Log.i("test :" , " "+ test);
holder.test.setText(testessen.get(position).getAverage());
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
};
recyclerView_aktuelle_Bewertungen.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView_aktuelle_Bewertungen.setAdapter(adapter);
recyclerView_aktuelle_Bewertungen.hasFixedSize();
adapter.startListening();
}
public class EssenViewHolder extends RecyclerView.ViewHolder{
TextView essenName, essenPreis, test;
public EssenViewHolder (@NonNull View itemView ) {
super(itemView);
essenName = itemView.findViewById(R.id.reihen_name);
essenPreis = itemView.findViewById(R.id.reihen_preis);
test = itemView.findViewById(R.id.reihen_test);
}
}
}
平均计算的输出是:对于食品测试1:
I/durchschnitt:12.5 4 3.125 -> 12.5/4 = 3.125
对于测试2:
I/durchschnitt:12.5 4 3.125 -> 12.5/4 = 3.125
对于测试3:
I/durchschnitt:2.5 1 2.5 -> 2.5/1 = 2.5
DB 中的条目: Test1: 3 + 3+ 4 +2.5 = 12.5 test 2: 3.5+3.5+3+2.5= 12.5 test 3: 2.5 = 2.5 计算似乎工作得很好......
这是我的埃森课程:
String name,Preis;
float average;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPreis() {
return Preis;
}
public void setPreis(String preis) {
Preis = preis;
}
public float getAverage() {
return average;
}
public void setAverage(float average) {
this.average = average;
}
public essen (String name, String Preis, float average){
this.name = name;
this.Preis = Preis;
this.average = average;
}
public essen(){}
}
这是我的 XML 布局文件,它显示在回收站视图中(我删除了所有不必要的视图,因此约束可能看起来有点奇怪):
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="90dp"
android:layout_margin="10dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/reihen_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/roboto"
android:text="Name"
android:textColor="@color/rot"
android:textSize="17sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.064"
app:layout_constraintStart_toEndOf="@+id/reihen_bilder"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.149" />
<TextView
android:id="@+id/reihen_preis"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/roboto"
android:text="Preis"
android:textColor="@color/black"
android:textSize="17sp"
android:textStyle="normal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.723"
app:layout_constraintStart_toEndOf="@+id/reihen_bilder"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.507" />
<TextView
android:id="@+id/reihen_test"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.552"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.14" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
这是我的 Firebase 数据库的屏幕截图:
解决方案
我现在看到您将平均值设置onDataChange
为计算数据之外的视图。那是行不通的,因为当你holder.test.setText(testessen.get(position).getAverage())
运行时,e.setAverage(durchschnitt)
还没有运行。
任何需要数据库数据的代码都需要在该数据的内部onDataChange
,或者从那里调用。
最简单的方法是只显示嵌套内部的平均值onDataChange
:
final ArrayList<essen> testessen =new ArrayList<>();
essenRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot ds : dataSnapshot.getChildren()){
final essen e = new essen();
e.name = ds.child("name").getValue(String.class);
e.Preis = ds.child("Preis").getValue(String.class);
bewertungenRef.addListenerForSingleValue(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
float sum = (float) 0.0;
int counter = 0;
for (DataSnapshot ds1 : dataSnapshot.getChildren()){
if (ds1.child("eid").getValue(String.class).equals(e.name)){
sum = sum + ds1.child("wert").getValue(float.class);
counter ++;
}
}
float durchschnitt = sum/counter;
Log.i("durchschnitt" , " " + sum + " "+ counter + " " +durchschnitt);
e.setAverage(durchschnitt);
Log.i("essen wert: " , " " + e.getAverage());
holder.essenName.setText(testessen.get(position).getName());
holder.essenPreis.setText(testessen.get(position).getPreis());
float test = (float) testessen.get(position).getAverage();
Log.i("test :" , " "+ test);
holder.test.setText(testessen.get(position).getAverage());
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
throw databaseError.toException(); // don't ignore errors
}
});
testessen.add(e);
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
throw databaseError.toException(); // don't ignore errors
}
});
在上面,您从 加载所有数据bewertungenRef
,而您只需要这些项目的一个子集。您还要为每次迭代重新加载该数据,这非常浪费(但应该可以)。
根据您拥有的数据量,您可能需要考虑仅加载bewertungenRef
所需的子节点。这意味着您有多个侦听器,这是一个很好的时机,也可以在加载所有数据后才更新 UI 中的平均值。
看起来像这样(未经测试,因此代码可能包含小问题):
final ArrayList<essen> testessen =new ArrayList<>();
essenRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
float sum = (float) 0.0;
int counter = 0;
// these variables track how many items we need to load, and how many we've already loaded
long essenCount = dataSnapshot.getChildrenCount();
long loadedCount = 0;
for (DataSnapshot ds : dataSnapshot.getChildren()){
final essen e = new essen();
e.name = ds.child("name").getValue(String.class);
e.Preis = ds.child("Preis").getValue(String.class);
bewertungenRef.orderByChild("eid").equalTo(e.name).addListenerForSingleValue(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot ds1 : dataSnapshot.getChildren()){
sum = sum + ds1.child("wert").getValue(float.class);
counter++;
}
if (loadedCount++ == essenCont) {
float durchschnitt = sum/counter;
e.setAverage(durchschnitt);
Log.i("essen wert: " , " " + e.getAverage());
holder.essenName.setText(testessen.get(position).getName());
holder.essenPreis.setText(testessen.get(position).getPreis());
holder.test.setText(testessen.get(position).getAverage());
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
throw databaseError.toException(); // don't ignore errors
}
});
testessen.add(e);
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
throw databaseError.toException(); // don't ignore errors
}
});
推荐阅读
- javascript - 如何从返回承诺的javascript ajax函数存储全局变量
- css - 我可以在 CSS 中总结一些时间值吗?
- php - 如何将产品详细信息从网站分享到 Facebook 和 LinkedIn
- python-3.x - TypeError:“NoneType”对象在创建 RESTful API 后端时不可下标
- python - Python continue 语句在 while 循环中的问题
- java - WELD-001408:在注入点 [BackedAnnotatedField] @Inject 具有限定符 @Default 的类型 Logger 的依赖关系不满足
- javascript - 有没有办法检查子 div 的底部?
- .net - CsvHelper 包:.netcoreapp3.0 不支持?
- visual-studio-code - 如何使用键盘专注于 git commit 消息输入 VSCode?
- android - 如何在 Android 上解释 mobilenetv2 分割结果输出?