Данные загружаются из Firebase асинхронно.
Поскольку для возврата данных с сервера может потребоваться некоторое время, а блокировка приложения в это время приведет к появлению диалогового окна «Приложение не отвечает», Firebase позволяет вашему приложению продолжить работу, показагрузка базы данных.Затем, когда данные возвращаются с сервера, клиент Firebase вызывает ваш метод onDataChange
с этими данными.
Самый простой способ убедиться в этом - добавить несколько операторов журнала в ваш код:
public List<Baustelle> readAll() {
Log.i(TAG, "Before attaching listener");
myRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.i(TAG, "Inside onDataChange");
}
@Override
public void onCancelled(DatabaseError error) {
Log.w(TAG, "Failed to read value.", error.toException());
}
});
Log.i(TAG, "After attaching listener");
}
Если вы запустите этот код, вы получите:
Перед подключением слушателя
После подключения слушателя
Внутри onDataChange
Вероятно, это не тот порядок, который вы ожидали.Но это прекрасно объясняет, почему pojoList
пусто, когда вы его возвращаете: данные просто еще не загружены.
Невозможно изменить это поведение: асинхронные API-интерфейсы свойственны программным приложениям против современныхвеб-API.Лучший способ справиться с этим поведением - это переосмыслить мои решения.Вместо того, чтобы думать «сначала прочитать все данные, а затем что-то сделать с ними», я считаю это «Начать загрузку всех данных. Всякий раз, когда данные читаются, что-то с ними делают».
На практике это означает, чтовесь код, которому нужны данные из базы данных, должен (вызываться из) внутри метод onDataChange
.Итак, скажем, что вы хотите напечатать загруженные данные, вы должны сделать:
public void readAll() {
myRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
pojoList= new LinkedList<>();
for (DataSnapshot postSnapshot: dataSnapshot.getChildren()) {
pojoList.add(postSnapshot.getValue(Baustelle.class));
}
Log.i(TAG, pojoList);
}
@Override
public void onCancelled(DatabaseError error) {
Log.w(TAG, "Failed to read value.", error.toException());
}
});
}
Теперь это делает ваш код немного менее гибким, поскольку вы кодируете запись в onDataChange
.Таким образом, вы также можете создать свой собственный интерфейс обратного вызова, как показано в моем ответе здесь: Метод getContactsFromFirebase () возвращает пустой список .Эта тема сбивает с толку многих разработчиков, плохо знакомых с Firebase.Я настоятельно рекомендую вам ознакомиться с некоторыми из предыдущих ответов, на которые есть ссылки.