Home > Back-end >  Recycle view showing single item from firebase realtime database
Recycle view showing single item from firebase realtime database

Time:08-15

My JSON is:

{
  "Ingredient": {
    "hgO9joLhmfh4Wjn7xYpyqcYmNOB3": {
      "Garlic": {
        "Expiry": "2022-11-12",
        "Ingredient": 1
      },
      "Onion": {
        "Expiry": "2022-11-12",
        "Ingredient": 1
      }
    }
  }
}

where hgO9joLhmfh4Wjn7xYpyqcYmNOB3 is the current user UID. The problem here is RecycleView shows only a single item from the database which in my case is Onion node. Why didn't it loop for each children under the fridgeRef.child(currentUserID) node?

java code

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    ingredientView = inflater.inflate(R.layout.fragment_fridge, container, false);
    
    myIngredientList = (RecyclerView) ingredientView.findViewById(R.id.ingredientList);
    myIngredientList.setLayoutManager(new LinearLayoutManager(getContext()));

    mAuth = FirebaseAuth.getInstance();
    currentUserID = mAuth.getCurrentUser().getUid();

    fridgeRef = FirebaseDatabase.getInstance().getReference().child("Ingredient");
    return ingredientView;
}

@Override
public void onStart() {
    super.onStart();

    FirebaseRecyclerOptions<fridgeItem> options
            new FirebaseRecyclerOptions.Builder<fridgeItem>()
                    .setQuery(fridgeRef , fridgeItem.class)
                    .build();

    FirebaseRecyclerAdapter<fridgeItem, fridgeViewHolder> adapter
            = new FirebaseRecyclerAdapter<fridgeItem, fridgeViewHolder>(options) {
        @Override
        protected void onBindViewHolder(@NonNull fridgeViewHolder holder, int position, @NonNull fridgeItem model) {

            fridgeRef.child(currentUserID).addValueEventListener(new ValueEventListener() {
                @Override
                public void onDataChange(@NonNull DataSnapshot snapshot) {

                    for(DataSnapshot dataSnapshot : snapshot.getChildren()){
                        if(snapshot.child("Garlic").hasChild("Ingredient")){
                            String itemName = "Garlic";
                            String itemExpiry = snapshot.child("Garlic").child("Expiry").getValue().toString();

                            holder.ingredName.setText(itemName);
                            holder.ingredExpiry.setText(itemExpiry);
                        }

                        if(snapshot.child("Onion").hasChild("Ingredient")){
                            String itemName = "Onion";
                            String itemExpiry = snapshot.child("Onion").child("Expiry").getValue().toString();

                            holder.ingredName.setText(itemName);
                            holder.ingredExpiry.setText(itemExpiry);
                        }
                    }
                }

                @Override
                public void onCancelled(@NonNull DatabaseError error) {

                }
            });
        }

        @NonNull
        @Override
        public fridgeViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.ingredientrecycle, parent, false);
            fridgeViewHolder viewHolder = new fridgeViewHolder(view);
            return viewHolder;
        }
    };

    myIngredientList.setAdapter(adapter);
    adapter.startListening();
}

public static class fridgeViewHolder extends RecyclerView.ViewHolder{

    TextView ingredName, ingredExpiry;

    public fridgeViewHolder(@NonNull View itemView) {
        super(itemView);

        ingredName = itemView.findViewById(R.id.itemName);
        ingredExpiry = itemView.findViewById(R.id.itemExpiry);
    }
}

ingredientrecycle.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    app:cardElevation="10dp"
    app:cardCornerRadius="12dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:weightSum="3">

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:layout_marginTop="16dp"
            android:orientation="vertical"
            android:layout_weight="2">

            <TextView
                android:id="@ id/itemName"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="@string/ingred"
                android:textSize="18sp"
                android:fontFamily="@font/roboto" />

            <TextView
                android:id="@ id/itemExpiry"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/expiry"
                android:textSize="16sp"
                android:layout_marginBottom="16dp"
                android:fontFamily="@font/roboto"/>
        </LinearLayout>

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_margin="16dp"
            android:gravity="end"
            android:layout_weight="1">

            <ImageView
                android:id="@ id/deleteBtn"
                android:layout_height="20dp"
                android:layout_width="20dp"
                android:src="@drawable/delete_icon"
                android:layout_marginEnd="32dp"/>
        </LinearLayout>
    </LinearLayout>
</androidx.cardview.widget.CardView>

fragment_fridge.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".fridge">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/fridge"
            android:textSize="22sp"
            android:layout_marginStart="32dp"
            android:layout_marginEnd="32dp"
            android:layout_marginTop="32dp"
            android:textStyle="bold"
            android:textColor="#FF5D36"
            android:fontFamily="@font/roboto"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/fridgetext"
            android:textSize="20sp"
            android:layout_marginStart="32dp"
            android:layout_marginEnd="32dp"
            android:fontFamily="@font/roboto"/>

        <ScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:paddingStart="32dp"
                android:paddingEnd="32dp"
                android:paddingTop="32dp">

                <androidx.recyclerview.widget.RecyclerView
                    android:id="@ id/ingredientList"
                    android:layout_width="match_parent"
                    android:layout_height="615dp" />

            </LinearLayout>
        </ScrollView>
    </LinearLayout>
</FrameLayout>

CodePudding user response:

The adapters from FirebaseUI are designed to show a single child view for each direct child node at the path where you attach the adapter in the database.

In your case, you attach the adapter to /Ingredient, so it creates a single view for each child node of /Ingredient, which is just one child node for hgO9joLhmfh4Wjn7xYpyqcYmNOB3. In that child node you then read handle both its Garlic and Onion properties, but you're setting their values on the same view holder - so you end up only seeing the values from Onion.


If you want to show all ingredients for /Ingredient/hgO9joLhmfh4Wjn7xYpyqcYmNOB3, you should attach the adapter to that path and simplify its handling to:

FirebaseRecyclerOptions<fridgeItem> options
        new FirebaseRecyclerOptions.Builder<fridgeItem>()
                .setQuery(fridgeRef.child("hgO9joLhmfh4Wjn7xYpyqcYmNOB3") , fridgeItem.class)
                .build();

FirebaseRecyclerAdapter<fridgeItem, fridgeViewHolder> adapter
        = new FirebaseRecyclerAdapter<fridgeItem, fridgeViewHolder>(options) {
    @Override
    protected void onBindViewHolder(@NonNull fridgeViewHolder holder, int position, @NonNull fridgeItem model) {

        // String itemName = "Garlic"; TODO:            
  • Related