#android #firebase #android-recyclerview #firebase-realtime-database
#Android #firebase #android-recyclerview #firebase-база данных в реальном времени
Вопрос:
Я работаю Firebase
и использую android.support.v7.widget.RecyclerView
. Проблема в том, что onStart
представление загружается пустым, а данные заполняются только после прокрутки. Есть идеи, почему?
Код :
RecyclerView (я устанавливаю пустой адаптер при запуске, чтобы избежать «RecyclerView: адаптер не подключен; пропуск макета») :
mLayoutManager = new LinearLayoutManager(getActivity());
mLayoutManager.setReverseLayout(true);
mLayoutManager.setStackFromEnd(true);
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.getRecycledViewPool().setMaxRecycledViews(1,0);
mRecyclerView.setAdapter(new RecyclerView.Adapter() {
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return null;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
}
@Override
public int getItemCount() {
return 0;
}
});
Выборка данных Firebase:
databaseReference.child("/News").orderByChild("createdAt").addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(final DataSnapshot dataSnapshot) {
for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
final News news = postSnapshot.getValue(News.class);
final PostListClass postListClass = new PostListClass();
//add fac id admin
if (news.getFaculteId().equals(userFaculteId) || news.getFaculteId().equals("Admin")) {
postListClass.setPostId(postSnapshot.getKey());
postListClass.setPostTitle(news.getHeadlines());
postListClass.setPostDescription(news.getDetails());
databaseReference.child("/users").child(news.getAuthor()).addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot usersSnapShot) {
User user = usersSnapShot.getValue(User.class);
postListClass.setPostOwnerId(usersSnapShot.getKey());
postListClass.setPostOwnerName(user.getPrenom() " " user.getNom());
postListClass.setPostOwnerPromo(user.getPromotion());
try {
Calendar cal = Calendar.getInstance(Locale.ENGLISH);
cal.setTimeInMillis(news.getCreatedAt() * 1000);
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
Date date = sdf.parse(DateFormat.format("dd-MM-yyyy", cal).toString());
String day = (String) android.text.format.DateFormat.format("dd", date);
String month = (String) android.text.format.DateFormat.format("MMM", date);
postListClass.setPostDate(day " " month);
} catch (java.text.ParseException e) {
e.printStackTrace();
}
storageRef.child("users/" news.getAuthor() ".jpg").getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
@Override
public void onSuccess(Uri uri) {
postListClass.setPostOwnerImageUrl(String.valueOf(uri));
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception exception) {
// Handle any errors
if (exception.getClass().isInstance(StorageException.class)) {
postListClass.setPostOwnerImageUrl("NullImage");
}
}
});
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
databaseReference.child("/News").child(postSnapshot.getKey()).child("/Comments").addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
postListClass.setPostComments(String.valueOf(dataSnapshot.getChildrenCount()));
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
storageRef.child("News/" postSnapshot.getKey() ".png").getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
@Override
public void onSuccess(Uri uri) {
postListClass.setPostImageUrl(String.valueOf(uri));
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception exception) {
postListClass.setPostImageUrl("NullImage");
}
});
postListClasses.add(postListClass);
}
}
postsAdapter = new PostsAdapter(getContext(), postListClasses);
mRecyclerView.setAdapter(postsAdapter);
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
Итак, это результат при запуске приложения (в трех полях отсутствуют данные) :
И после прокрутки (заполняются недостающие данные) :
Ответ №1:
Данные загружаются из Firebase асинхронно. Поэтому, когда вы подключаете адаптер к списку, данных еще нет.
Как только данные поступают с сервера, вам нужно предупредить об этом список. Вы делаете это, вызывая adapter.notifyDataSetChanged()
.
Комментарии:
1. Спасибо за ваш ответ, я только что добавил
adapter.notifyDataSetChanged()
, все та же проблема. Дело в том, что заголовок и содержимое загружены, но данные из второй выборки данных Firebase не загружаются, пока я не прокручиваю представление recycler.2. Вероятно, они загружены, но просто не отображаются. В общем случае это включает в себя информирование адаптера (и оттуда представление) о том, что данные изменились.
3. Мой плохой, я закончил добавление
adapter.notifyDataSetChanged()
после второй выборки, и это сработало, спасибо.4. Вы зашли довольно далеко, так что это только последний шаг. К сожалению, об этом легко забыть или просто не знать. Приятно слышать, что у вас это работает!