Currently, I am make a social media app and I am using firebase firestore and cloud storage for my project. There is a comment button and if the user clicks the button he should be able to see every users' comments with their name and profile image.
This is my firestore database structure,
Users(Root collection)
|---- UID1([Document]User ID which generate by authentication)---[Fields-Name,Image,Age]
|---- UID2([Document]User ID which generate by authentication)---[Fields-Name,Image,Age]
Posts(Root collection)
|-----DOCID1(Fields-Post Title,Posted_UID,Post_Image)
|----Comments(Sub-collection)
|----1RANDOMDOCID(Fields-Commented_User_Id,Commented_Date,Comment)
|----2RANDOMDOCID(Fields-Commented_User_Id,Commented_Date,Comment)
Alright, I need to populate these comments to a recycleview. I ll add my approach below,
Query query = db.collection("Posts").document(CURRENT_SELECTED_DOC_ID).collection("Comments");
PagedList.Config config = new PagedList.Config.Builder()
.setEnablePlaceholders(false)
.setInitialLoadSizeHint(10)
.setPageSize(20)
.build();
FirestorePagingOptions<CommentsI> options = new FirestorePagingOptions.Builder<CommentsI>()
.setQuery(query, config, CommentsI.class)
.build();
Constructor
public class CommentI {
String Commented_User_Id;
Date Commented_Date;
String Comment;
public CommentI(){
//Empty constructor
}
public class CommentI(String commented_User_Id,Date commented_Date,String comment){
Commented_User_Id = commented_User_Id;
Commented_Date = commented_Date;
Comment = comment;
//------------------------------------------
public String getCommented_User_Id(){
return Commented_User_Id;
}
public Date getCommented_Date(){
return Commented_Date;
}
public String getComment(){
return Comment;
}
This is the usual way to populate items in recycleview. I can get these comments and date without any doubt, But I need to set the users' Image and name same time. this is the point where I had to stop my work until solve this. Please someone help :)
Edit
Here is my adapter and when we trying retrieve user info like this, it always reads the firestore document while scrolling up and down. For example - When I scrolling up and down(Just think i got 10 items in recyleview), I can see name and image refreshing everytime when scrolling from item 1 to 10 and from item 10 to 1. How to fix this?
@Override
protected void onBindViewHolder(@NonNull final CommentIViewHolder holder, int position, @NonNull CommentI model) {
holder.comment_textview.setText(model.getComment());
holder.date_textview.setText(DateFormat.format("(yyyy-MM-dd)", model.getCommented_Date()));
//getting UserID-------------
String UserId = model.getCommented_User_Id();
final FirebaseFirestore db = FirebaseFirestore.getInstance();
DocumentReference documentReference = rootRef.collection("Users").document(UserId);
documentReference.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
@Override
public void onComplete(@NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()){
DocumentSnapshot doc = task.getResult();
if (doc.exists()) {
String UserName = doc.getString("Name");
String UserImage = doc.getString("Image");
holder.commentor_name.setText(UserName);
holder.setProfile_image_view(UserImage);
}
}
}
});
Okay, my bad. I suggested you to use the Firebase User object to store the image URL but you can only get the image of the current user (which is not what you want).
So storing in the database is needed. Now, as @Greg said that you have two approaches and I would also recommend having the second but if your use case is such that you need to have the first approach then here's what you do:
1. Store the user's UID in the comments documents (which you have already done).
2. Get the comments of the particular post (which too, you have already done).
Now, after this, you are getting the user's document in
onBindViewHolder
which is strongly discouraged as because youronBindViewHolder
would be called many times in yourrecyclerView
which would have performance issues and cost uprising.By seeing your code, I am assuming that you are using FirebaseUI (with which I have no experience) but I think you should do this approach on your own like this (I recently had such case and did like this):
3. Get the comments of the particular post and store it in something like an
ArrayList
.4. Loop over the comments, get each user's documents and store them also in
Arraylist
.5. Pass both the
ArrayLists
in your constructor of the adapter and then just set them up inonBindViewHolder
.Now, when I was doing something similar like this, I got an unusual behaviour which you should see here (if you are following this answer) in my question (with the answer given by myself): Running Firebase get() in a loop in android
Although, this would cost you a lot!