Android: получить список Pojo из Firebase во время первой инициализации из класса обслуживания - PullRequest
0 голосов
/ 02 июня 2018

Я пытаюсь получить список всех моих "Baustelle" Pojos от Firebase.Мой класс обслуживания - Singelton, и в конструкторе я вызываю метод initialize, который вызывает метод readAll ().Так почему «readAll ()» не работает правильно?Он запускает onDataChange задолго после возврата, поэтому он возвращает ноль вместо списка Pojo.

Служба

public class Service {
    private static volatile Service instance = null;
    private List<Baustelle> bauList = new LinkedList<>();
    private BaustellenDao bauDao = new BaustellenDao();


    public void initialize(){
       bauList = bauDao.readAll();
    }

   private Service(){
        initialize();
    }

    public static synchronized Service getInstance(){
        if(instance==null)
            instance = new Service();
        return instance;
    }
}

DAO

public class BaustellenDao implements BaseDao<Baustelle> {
    private FirebaseDatabase database = FirebaseDatabase.getInstance();
    DatabaseReference myRef = database.getReference("baustellen");
    private List<Baustelle> pojoList=  null;


    @Override
    public List<Baustelle> readAll() {
        // Read from the database

        myRef.addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                    pojoList= new LinkedList<>();
                for (DataSnapshot postSnapshot: dataSnapshot.getChildren()) {
                    pojoList.add(postSnapshot.getValue(Baustelle.class));
                }




            }

            @Override
            public void onCancelled(DatabaseError error) {
                // Failed to read value
                Log.w(TAG, "Failed to read value.", error.toException());
            }
        });


        return pojoList;
    }
} 

1 Ответ

0 голосов
/ 02 июня 2018

Данные загружаются из 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.Я настоятельно рекомендую вам ознакомиться с некоторыми из предыдущих ответов, на которые есть ссылки.

...