Я пытаюсь передать строку (userID) из onBindViewHolder в свой класс ViewHolder. Причина в том, что мне нужна позиция для выделения правильного postID. Этот postID используется во ViewHolder в качестве ссылки для настройки Firebase valueEventListener. Однако при запуске приложения я получаю NullPointerException в postID. Это из-за синхронизации? Вызывается ли valueEventListener до установки postID?
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
final PostViewHolder holder1 = (PostViewHolder) holder;
holder1.postID = getPostId(position)
//...
}
//...
public class PostViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
private DatabaseReference mNoOfLikesRef;
public String postID;
//...
public PostViewHolder(View itemView, postClickListener listener){
super(itemView);
//This line causes the NullPointerException on postID
mNoOfLikesRef = FirebaseDatabase.getInstance().getReference().child("likes").child(postID);
ValueEventListener valueEventListener = new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
//...
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
};
mNoOfLikesRef.addListenerForSingleValueEvent(valueEventListener);
}
Спасибо за ваши комментарии. @ADM, да, postID у каждого элемента разный. Причина, по которой я не установил его в onBindViewHolder, заключается в том, что я пытаюсь предотвратить вызов базы данных Firebase при каждой привязке представления. Я понял, что это нужно установить в onCreateViewHolder, но опять же, это зависит от позиции, которой у меня нет на данном этапе.
Слушатель для каждого пункта списка кажется мне довольно беспокойным. Зачем это нужно? Если у вас есть 100 пунктов списка, будет 100 слушателей. IMHO, вы должны зарегистрировать одного слушателя в корневом каталоге и использовать DiffUtil для уведомления об изменениях в адаптере. Если это покрытие вашей потребности! В противном случае вам нужно управлять слушателями, когда представление строки повторно используется во время прокрутки.
@ADM, на самом деле у меня есть следующее: я использую Firestore для сохранения сообщений, временных меток и т. д. И передаю их в виде списка в адаптер. Каждому из этих постов можно понравиться или не понравиться, и у меня есть счетчик лайков / антипатий в Firebase RTDB (многие операции и использование транзакций). Использование DiffUtil в корневом каталоге будет запускаться для каждого лайка / антипатии в любом посте :(.
ОК . Что делать, если добавлен новый пост? Как добавить новую запись в адаптер? Или в том же корне нового поста не будет?
Дополнительная информация о моем коде - здесь, если кому-то интересно. До сих пор я не нашел «подходящего» решения для функциональности лайков / антипатий с помощью firebase, это создавало огромные накладные расходы протокола (как проверено с помощью Stackdriver) из-за частых запросов.
Да, вы вызываете его в конструкторе PostViewHolder, который вызывается методом onCreateViewHolder перед onBindViewHolder.
создать метод внутри класса ViewHolder и вызвать его из onBindViewHolder
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
final PostViewHolder holder1 = (PostViewHolder) holder;
holder1.doYourTask(getPostId(position));
//...
}
public class PostViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
//...
public void doYourTask(String postID){
DatabaseReference mNoOfLikesRef = FirebaseDatabase.getInstance().getReference().child("likes").child(postID);
ValueEventListener valueEventListener = new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
//...
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
};
mNoOfLikesRef.addListenerForSingleValueEvent(valueEventListener);
}
}
Это то, что он пытался сказать. Я попытался написать его первым, но Шалауддин Ахамад Шуза оказался быстрее. Если вы получаете NullPointerException не потому, что вы его неправильно передаете, это означает, что getPostId(position) не возвращает правильное значение.
При использовании этого подхода SingleValueEventListener запускается каждый раз при привязке нового просмотра, верно? Я как-то хотел предотвратить это, вызвав это в самом ViewHolder. Есть ли способ сделать это?
Опубликуйте исходный код get postId (position)