首页 > 解决方案 > 当我计算食物的平均评分时,将此值保存到显示为 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 数据库的屏幕截图:

在此处输入图像描述

标签: androidfirebase-realtime-databasearraylistpojo

解决方案


我现在看到您将平均值设置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
    }
});


推荐阅读