#java #android #database #firebase #comments
#java #Android #База данных #firebase #Комментарии
Вопрос:
Я могу получить данные в коллекции firebase, но он не запрашивает эти данные в представлении recycler. Recyclerview ничего не показывает
Это класс comment_list .
public class comment_list {
public comment_list(String comments) {
this.comments = comments;
}
public String getComments() {
return comments;
}
public void setComments(String comments) {
this.comments = comments;
}
String comments;
}
Это класс comment_adapter
public class comment_adapter extends FirestoreRecyclerAdapter<comment_list, comment_adapter.comment_holder> {
public comment_adapter(@NonNull FirestoreRecyclerOptions<comment_list> options) {
super(options);
}
@Override
protected void onBindViewHolder(@NonNull comment_holder holder, int position, @NonNull comment_list model) {
holder.commment_on_post.setText(model.getComments());
}
@NonNull
@Override
public comment_holder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.comment_recycler_dsign, parent, false);
return new comment_holder(v);
}
public class comment_holder extends RecyclerView.ViewHolder{
TextView commment_on_post;
public comment_holder(@NonNull View itemView) {
super(itemView);
commment_on_post = itemView.findViewById(R.id.commenttextview);
}
}
Это класс комментариев. При этом я могу получать данные в коллекции firebase, но они не запрашивают эти данные в представлении recycler.
public class Comments extends AppCompatActivity {
ImageView profileimage;
EditText addcommenttext;
TextView postcommenttext;
FirebaseFirestore db;
RecyclerView comment_recycler_view;
comment_adapter adaptercomment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_comments);
profileimage = findViewById(R.id.Addcommentprofileimage);
addcommenttext = findViewById(R.id.addcommenttext);
postcommenttext = findViewById(R.id.postcomment);
comment_recycler_view = findViewById(R.id.commentsrecycler);
postcommenttext.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (addcommenttext.equals("")) {
Toast.makeText(Comments.this, "Comment can't be empty", Toast.LENGTH_SHORT).show();
} else {
String commentText = addcommenttext.getText().toString();
CollectionReference commentref = FirebaseFirestore.getInstance() .collection("CommentDetails");
commentref.add(new comment_list(commentText));
FirebaseFirestore fbfs = FirebaseFirestore.getInstance();
CollectionReference commentrefs = fbfs.collection("CommentDetails");
Query query = commentrefs;
FirestoreRecyclerOptions<comment_list> options = new FirestoreRecyclerOptions.Builder<comment_list>()
.setQuery(query, comment_list.class)
.build();
adaptercomment = new comment_adapter(options);
comment_recycler_view.setHasFixedSize(true);
comment_recycler_view.setLayoutManager(new LinearLayoutManager(getApplication()));
comment_recycler_view.setAdapter(adaptercomment);
finish();
Toast.makeText(Comments.this, "Commented", Toast.LENGTH_SHORT).show();
}
}
});
}
Комментарии:
1. Пожалуйста, опубликуйте свою структуру базы данных
2. Данные в вашей базе данных
3. ваша средняя коллекция в облачном firestore?
4. Пожалуйста, отредактируйте свой вопрос и добавьте свою структуру базы данных в виде скриншота. Пожалуйста, ответьте с помощью @AlexMamo
5. @AlexMamo я сделал, пожалуйста, проверьте
Ответ №1:
Прежде всего, давайте перенастроим ваш класс активности комментариев. Было бы рекомендовано инициализировать адаптер recycle в вашем onCreate
методе, а не в переопределенном onClick
методе. При текущей настройке новый comment_adapter инициализируется каждый раз, когда запускается прослушиватель onClick. Лучше всего, чтобы мы настроили только один. Вот как все выглядит после изменений (я добавил комментарии для ясности):
ПРИМЕЧАНИЕ: я переименовал классы, переменные и методы, чтобы использовать соглашения java и Android для ясности. Изучение этого очень поможет вам в чтении чужого кода и избавит вас от множества головных болей с вашим собственным кодом.
public class CommentsActivity extends AppCompatActivity {
FirebaseFirestore db;
CommentAdapter commentAdapter;
ImageView profileImageView;
EditText commentEditText;
RecyclerView commentRecyclerView;
Button addCommentButton; // Replaces the text view you are using
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
profileImageView = findViewById(R.id.add_comment_profile_image);
commentEditText = findViewById(R.id.comment_edit_text);
addCommentButton = findViewById(R.id.add_comment_button);
commentRecyclerView = findViewById(R.id.comments_recycle_view);
// Enables firestore debugging which will help a lot when trying to troubleshoot
FirebaseFirestore.setLoggingEnabled(true);
// We are now setting up our query directly within the OnCreate method.
db = FirebaseFirestore.getInstance();
Query query = db.collection("CommentDetails").orderBy("timestamp").limit(50);
FirestoreRecyclerOptions<Comment> options = new FirestoreRecyclerOptions.Builder<Comment>()
.setQuery(query, Comment.class)
.build();
// Setting up the recycle adapter in onCreate
commentAdapter = new CommentAdapter(options);
commentRecyclerView.setLayoutManager(new LinearLayoutManager(this));
commentRecyclerView.setAdapter(commentAdapter);
// Set up your onClickListener just as before.
addCommentButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Note that the previous null check is unsuccessful. Previously, the object instance
// was being checked, and not the contents of the edit text. This resolves that issue. (:
if (commentEditText.toString().isEmpty()) {
Toast.makeText(CommentsActivity.this, "Comment can't be empty", Toast.LENGTH_SHORT).show();
} else {
String commentText = commentEditText.getText().toString();
CollectionReference commentColRef = FirebaseFirestore.getInstance().collection("CommentDetails");
commentColRef.add(new Comment(commentText));
Toast.makeText(CommentsActivity.this, "Commented", Toast.LENGTH_SHORT).show();
}
}
});
}
@Override
protected void onStart() {
super.onStart();
commentAdapter.startListening();
}
@Override
protected void onStop() {
super.onStop();
commentAdapter.stopListening();
}
}
Вы заметите добавление двух новых методов: onStart
и onStop
. В рамках этих методов мы запускаем и останавливаем прослушиватели запросов, подключенные к FirestoreRecyclerAdapter
. Будет очень полезно обратиться к FirebaseUI для чтения в облачном Firestore.
Важно отметить, что в приведенном выше коде я также переименовал вашу модель данных из comment_list в Comment . Причина этого в том, что экземпляр этого класса хранит состояние только одного комментария. Он не хранит список комментариев. Я думаю, что это может вызвать путаницу, когда вы пытаетесь отладить свой код. В случае использования FirebaseUI фактический список комментариев (список комментариев), который привязан к вашему представлению recycle, создается для вас кодом FirebaseUI в виде массива экземпляров класса комментариев.
Чтобы четко понять, как это делается, может быть полезно потратить пару часов на реализацию простого представления recycle и адаптера, который не подключен к Firestore. Таким образом, можно получить более глубокое понимание того, как FirebaseUI работает. Здесь есть документы по этому вопросу.
Наконец, вот замена классу comment_list:
public class Comment {
String comment;
@ServerTimestamp Date timestamp;
// A zero argument constructor is required by firestore.
public Comment() {
}
public Comment(String comment) {
this.comment = comment;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public Date getTimestamp() {
return timestamp;
}
public void setTimestamp(Date timestamp) {
this.timestamp = timestamp;
}
Единственное отличие здесь в том, что здесь есть конструктор с нулевыми аргументами (без аргументов), который требуется firestore.
Слово мудрому — я не видел ваш макет элемента модели представления ( comment_recycler_dsign
), но просто проверьте, что корневой макет не имеет высоты «match_parent». Это распространенная ошибка. Рекомендуется сначала проверить это, если вы видите, что отображается только один элемент recycle.
Комментарии:
1. Это работает, спасибо. Не могли бы вы сказать мне, как я могу заказать запрос, например, если я оставлю комментарий, тогда он появится сверху, а затем появится сверху?
2. Возникает проблема, связанная с тем, что каждый комментарий отображается в каждом сообщении, а не в одном сообщении
3. @Harnoor Попробуйте добавить поле «timestamp» в класс комментариев. Каждый раз, когда делается комментарий, публикуйте временную метку вместе с ним. Затем отредактируйте запрос firebase, чтобы
Query query = db.collection("chats").orderBy("timestamp").limit(50);
посмотреть ( github.com/firebase/FirebaseUI-Android/tree/master /… ). Пример реализации идеально подходит для того, что вы пытаетесь сделать. (= Удачи!4. Не работает должным образом, комментарий размещен неточно, означает, что комментарий не размещен в соответствии с самым новым первым появлением
5. @Harnoor Вот рабочая реализация, на которую вы тоже можете сослаться. (: ( github.com/michael-lundie/stackoverflow_temp ) Я также обновил код в приведенном выше ответе с помощью функции временной метки.
Ответ №2:
Поместите слушателя, который fire base автоматически вызовет после завершения загрузки
firestore.collection("").add(Any()).addOnCompleteListener {
// do all your work here
}
Комментарии:
1. Операционная система Harnoor использует FirebaseUI и
FirestoreRecyclerAdapter
. В этом случае слушатели обрабатываются через адаптер, вызывая егоstartListening()
иstopListening()
методы соответственно. Однако, конечно, это потребуется в случае использования вашей собственной реализации пользовательского адаптера.