skip to Main Content

enter image description here

I have this structure in my Firestore, I want the logged-in user to be able to get all image URLs and other fields such as name, price, and description that are associated with that userID. This info will be loaded into a recyclerView.

This is the Item Model

package com.bac.shoesrecyclerview;


public class Item {
    private String itemName;
    private String itemPrice;
    private String itemDescription;
    private String itemImage;

public Item(String itemName, String itemPrice, String itemDescription, String itemImage) {
    this.itemName = itemName;
    this.itemPrice = itemPrice;
    this.itemDescription = itemDescription;
    this.itemImage = itemImage;

}
public Item(){

}
public String getItemName() {
    return itemName;
}

public void setItemName(String itemName) {
    this.itemName = itemName;
}

public String getItemPrice() {
    return itemPrice;
}

public void setItemPrice(String itemPrice) {
    this.itemPrice = itemPrice;
}

public String getItemDescription() {
    return itemDescription;
}

public void setItemDescription(String itemDescription) {
    this.itemDescription = itemDescription;
}

public String getItemImage() {
    return itemImage;
}

public void setItemImage(String itemImage) {
    this.itemImage = itemImage;
}

}

This is the code i tried and crushes my app :

fStore.collection("images").document(FirebaseAuth.getInstance().getCurrentUser().getUid()).get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
        @Override
        public void onComplete(@NonNull Task<DocumentSnapshot> task) {
            if(task.isSuccessful()){
                DocumentSnapshot document = task.getResult();
                Item item = new Item();
                itemList = new ArrayList<>();
                while (document.exists()){

                    item.setItemName(document.getString("name"));
                    item.setItemPrice(document.getString("price"));
                    item.setItemDescription(document.getString("description"));
                    item.setItemImage(document.getString("image"));
                    itemList.add(item);
                }
                shoeAdapter = new ShoeAdapter(MainActivity.this, itemList);
                recyclerView.setAdapter(shoeAdapter);
                shoeAdapter.notifyDataSetChanged();
            }
        }

2

Answers


  1. Try below query to get multiple document for single user-

        db.collection("images")
            .whereEqualTo("user_id", FirebaseAuth.getInstance().getCurrentUser().getUid())
            .get()
            .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                @Override
                public void onComplete(@NonNull Task<QuerySnapshot> task) {
                    if (task.isSuccessful()) {  
                        for (QueryDocumentSnapshot document : task.getResult()) {
                               Item item = new Item();
                               item.setItemName(document.getString("name"));
                               item.setItemPrice(document.getString("price"));
                               item.setItemDescription(document.getString("description"));
                               item.setItemImage(document.getString("image"));
                               itemList.add(item);
                        }
                shoeAdapter = new ShoeAdapter(MainActivity.this, itemList);
                        recyclerView.setAdapter(shoeAdapter);
                        shoeAdapter.notifyDataSetChanged();
                    } else {
                        Log.d(TAG, "Error getting documents: ", task.getException());
                    }
                }
            });
    

    Check document for more such queries – https://firebase.google.com/docs/firestore/query-data/queries

    Login or Signup to reply.
  2. There is no need to get the value of each field separately. You can directly map a child in the Realtime Database into an object of type Item. In order to be able to do that, you have to change the declaration of the class like this:

    public class Item {
        private String name;
        private String price;
        private String description;
        private String image;
        private String userId;
    
        public Item(String name, String price, String description, String image, String userId) {
            this.name = name;
            this.price = price;
            this.description = description;
            this.image = image;
            this.userId = userId;
    
        }
        public Item(){
    
        }
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getPrice() {
            return price;
        }
    
        public void setPrice(String price) {
            this.price = price;
        }
    
        public String getDescription() {
            return description;
        }
    
        public void setDescription(String description) {
            this.description = description;
        }
    
        public String getImage() {
            return image;
        }
    
        public void setImage(String image) {
            this.image = image;
        }
    
        public String getUserId() {
            return userId;
        }
    
        public void setUserId(String userId) {
            this.userId = userId;
        }
    }
    

    Why? Because the name of the fields inside the class should name the name that exists in the database.

    Now, in order to get the images that correspond to a logged-in user, you have to initialize the list, the adapter, and the RecyclerView and create a query that looks like this:

    itemList = new ArrayList<>();
    shoeAdapter = new ShoeAdapter(MainActivity.this, itemList);
    recyclerView.setAdapter(shoeAdapter);
    
    String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
    FirebaseFirestore db = FirebaseFirestore.getInstance();
    Query queryByUserId = db.collection("images").whereEqualTo("userId", uid);
    queryByUserId.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
        @Override
        public void onComplete(@NonNull Task<QuerySnapshot> task) {
            if (task.isSuccessful()) {
                for (QueryDocumentSnapshot document : task.getResult()) {
                    if (document != null) {
                        Item item = document.toObject(Item.class);
                        itemList.add(item);
                        Log.d("TAG", item.getName());
                    }
                }
                shoeAdapter.notifyDataSetChanged();
            } else {
                Log.d("TAG", task.getException().getMessage()); //Never ignore potential errors!
            }
        }
    });
    

    The changes that I made:

    1. There is no need to use a while loop. You only have to check against nullity.
    2. I have added the declaration related to UI outside the async operation. Once the operation for getting the Item objects is complete we only notify the adapter about the changes.
    3. Always handle errors.
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search