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>
2
Answers
You didn’t put the conditions inside the foreach loop
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 forhgO9joLhmfh4Wjn7xYpyqcYmNOB3
. In that child node you then read handle both itsGarlic
andOnion
properties, but you’re setting their values on the same view holder – so you end up only seeing the values fromOnion
.If you want to show all ingredients for
/Ingredient/hgO9joLhmfh4Wjn7xYpyqcYmNOB3
, you should attach the adapter to that path and simplify its handling to:You’ll still need to get the
itemName
from the database here. If that’s not in yourfridgeItem
class yet, you can get it with something likegetRef(position).getKey()
iirc.If you want to show all ingredients for all users, that doesn’t fit with the logic of the adapters in FirebaseUI, and you’re probably better off creating your own adapter.
/Ingredients
as you already do.getChildren()
of the data snapshot to get the snapshot for each user.