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) {
}
});
}