I am trying to retrieve data (a product image and the price for it) from Firebase Realtime Database and put it in a recyclerView, but I have some difficulties. In my database I stored the image url for one product and I want to show that image in an ImageView component placed in the cardView. I also managed to retrieve the url and price correctly, but my recyclerView doesn’t show them. This is my product class:
public class CustomizeProduct { private String productImage; private String productName; private String productPrice; public CustomizeProduct(String image, String name, String price){ this.productImage = image; this.productName = name; this.productPrice = price; } public String getProductImage() { return productImage; } public void setProductImage(String productImage){ this.productImage = productImage; } public String getProductName() { return productName; } public void setProductName(String productName){ this.productName = productName; } public String getProductPrice() { return productPrice; } public void setProductPrice(String productPrice) { this.productPrice = productPrice; } }
My Adapter as following:
public class ProductAdapter extends RecyclerView.Adapter<ProductAdapter.ViewHolder> { private ArrayList<CustomizeProduct> customized; private Context myContext; public static class ViewHolder extends RecyclerView.ViewHolder { public ImageView thisProductImage; public TextView thisProductName; public TextView thisProductPrice; public ViewHolder(View itemView) { super(itemView); thisProductImage = itemView.findViewById(R.id.customProductImage); thisProductName = itemView.findViewById(R.id.customProductName); thisProductPrice = itemView.findViewById(R.id.customProductPrice); } } public ProductAdapter(Context context, ArrayList<CustomizeProduct> thisCustom) { myContext = context; customized = thisCustom; } public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.ingredients, parent, false); ViewHolder mv = new ViewHolder(v); return mv; } public void onBindViewHolder(ViewHolder holder, int position) { CustomizeProduct currentCustom = customized.get(position); Picasso.get().load(currentCustom.getProductImage()).placeholder(R.drawable.shrimp_ditali).into(holder.thisProductImage); holder.thisProductName.setText(currentCustom.getProductName()); holder.thisProductPrice.setText(currentCustom.getProductPrice()); } public int getItemCount() { return customized.size(); } }
And the activity I have placed my recyclerView:
public class BuildProduct extends AppCompatActivity { public final static ArrayList<CustomizeProduct> customized = new ArrayList<>(); private RecyclerView recyclerView; private ProductAdapter myAdapter; private RecyclerView.LayoutManager layoutManager; private static String productImage, productPrice; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_build_product); buildCustom(); } public void buildCustom(){ recyclerView = findViewById(R.id.customList); recyclerView.setHasFixedSize(true); layoutManager = new LinearLayoutManager(this); final DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("MENIU"); ref.addListenerForSingleValueEvent(new ValueEventListener(){ public void onDataChange(DataSnapshot ds) { for (DataSnapshot menu : ds.getChildren()) { String keys = menu.getKey(); String productName = (String) ds.child(keys).child("NUME_PRODUS").getValue(); if(productName.equals(checkout.thisProductName)){ productImage = ds.child(keys).child("IMAGINE").getValue(String.class); Long price = (Long) ds.child(keys).child("PRET_PRODUS").getValue(); productPrice = String.valueOf(price); Toast.makeText(getApplicationContext(), productImage + " " + productPrice, Toast.LENGTH_LONG).show(); } } } @Override public void onCancelled(@NonNull DatabaseError databaseError) { } }); for(int i = 0; i < checkout.thisProductQty; i++) { customized.add(new CustomizeProduct(productImage,checkout.thisProductName, productPrice)); myAdapter = new ProductAdapter(getApplicationContext(), customized); } recyclerView.setLayoutManager(layoutManager); recyclerView.setAdapter(myAdapter); } }
The product name is correctly because is a variable, but the image and price don’t change at all. The “for” loop serves in creating as much cardViews as my products of that type are in checkout. How can I make it show image and price from database?
This is my Firebase child structure:
EDIT Updated code:
public class CustomizeProduct { private String imagine; private String nume_produs; private String pret_produs; public CustomizeProduct(){} public CustomizeProduct(String imagine, String nume_produs, String pret_produs){ this.imagine = imagine; this.nume_produs = nume_produs; this.pret_produs = pret_produs; } @PropertyName("IMAGINE") public String getIMAGINE() { return imagine; } @PropertyName("NUME_PRODUS") public String getNUME_PRODUS() { return nume_produs; } @PropertyName("PRET_PRODUS") public String getPRET_PRODUS() { return pret_produs; } }
And in onBindViewHolder:
public void onBindViewHolder(ViewHolder holder, int position) { CustomizeProduct currentCustom = customized.get(position); Picasso.get().load(currentCustom.getIMAGINE()).placeholder(R.drawable.shrimp_ditali).into(holder.thisProductImage); holder.thisProductName.setText(currentCustom.getNUME_PRODUS()); holder.thisProductPrice.setText(currentCustom.getPRET_PRODUS()); }
Advertisement
Answer
customized.add(new CustomizeProduct(productImage,checkout.thisProductName, productPrice));
You can see only product name (checkout.thisProductName
), but not product image & price because you populate your adapter with product names that is not returned by Firebase in your onDataChange(DataSnapshot ds)
callback; there is no clue in your code how do you build product names (checkout.thisProductName
) value.
Now product images & prices not shown as you build the adapter in the main thread, while firebase works implicitly in background thread; so you need to sync your adapter to that background thread by transferring the part of code that builds your recyclerView adapter into the firebase callback as follow:
public void buildCustom(){ recyclerView = findViewById(R.id.customList); recyclerView.setHasFixedSize(true); layoutManager = new LinearLayoutManager(this); final DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("MENIU"); ref.addListenerForSingleValueEvent(new ValueEventListener(){ public void onDataChange(DataSnapshot ds) { for (DataSnapshot menu : ds.getChildren()) { String keys = menu.getKey(); String productName = (String) ds.child(keys).child("NUME_PRODUS").getValue(); if(productName.equals(checkout.thisProductName)){ productImage = ds.child(keys).child("IMAGINE").getValue(String.class); Long price = (Long) ds.child(keys).child("PRET_PRODUS").getValue(); productPrice = String.valueOf(price); Toast.makeText(getApplicationContext(), productImage + " " + productPrice, Toast.LENGTH_LONG).show(); } } // here you've received all Firebase data and can now build the recyclerView for(int i = 0; i < checkout.thisProductQty; i++) { customized.add(new CustomizeProduct(productImage,checkout.thisProductName, productPrice)); myAdapter = new ProductAdapter(getApplicationContext(), customized); } recyclerView.setLayoutManager(layoutManager); recyclerView.setAdapter(myAdapter); } @Override public void onCancelled(@NonNull DatabaseError databaseError) { } }); }