Java netbeans не весь текст, показанный на JFrame, с использованием токенизатора и использование цикла for [duplicate]

Это классическая проблема с асинхронными веб-интерфейсами. Вы не можете вернуть то, что еще не загружено. Другими словами, вы не можете просто создать глобальную переменную и использовать ее вне метода onDataChange(), потому что она всегда будет null. Это происходит потому, что метод onDataChange() называется асинхронным.

Но не только Firebase Realtime Database загружает данные асинхронно, почти все современные другие сети API, так как это может занять некоторое время. Поэтому вместо того, чтобы ждать данных (что может привести к невосприимчивым диалоговым окнам приложений для ваших пользователей), ваш основной код приложения продолжается, пока данные загружаются во вторичный поток. Затем, когда данные доступны, вызывается метод onDataChange () и может использовать данные. Другими словами, к тому времени, когда метод onDataChange() называется, ваши данные еще не загружены.

Давайте возьмем пример, разместив несколько кодов журнала в коде, чтобы более четко видеть, что происходит.

private String getUserName(String uid) {
    Log.d("TAG", "Before attaching the listener!");
    databaseReference.child(String.format("users/%s/name", uid)).addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            // How to return this value?
            dataSnapshot.getValue(String.class);
            Log.d("TAG", "Inside onDataChange() method!");
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {}
    });
    Log.d("TAG", "After attaching the listener!");
}

Если мы запустим этот код, выход wil будет:

Перед присоединением слушателя!

После присоединения слушателя!

Внутри метода onDataChange ()!

blockquote>

Это, вероятно, не то, что вы ожидали, но оно точно объясняет, почему ваши данные null при возврате.

Первоначальный ответ для большинства разработчиков заключается в том, чтобы попытаться «исправить» это asynchronous behavior, что я лично рекомендую против этого. Интернет является асинхронным, и чем скорее вы примете это, тем скорее вы сможете узнать, как стать продуктивным с помощью современных веб-API.

Я нашел проще всего пересмотреть проблемы для этой асинхронной парадигмы. Вместо того, чтобы говорить «Сначала получить данные, а затем занести в журнал», я создаю проблему как «Начать получать данные. Когда данные загружаются, запишите их». Это означает, что любой код, который требует данных, должен быть внутри метода onDataChange() или вызван изнутри, например:

databaseReference.child(String.format("users/%s/name", uid)).addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        // How to return this value?
        if(dataSnapshot != null) {
            System.out.println(dataSnapshot.getValue(String.class));
        }
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {}
});

Если вы хотите использовать это снаружи, есть другой подход. Вам нужно создать свой собственный обратный вызов, чтобы ждать, пока Firebase вернет вам данные. Для этого сначала нужно создать interface следующим образом:

public interface MyCallback {
    void onCallback(String value);
}

Затем вам нужно создать метод, который фактически получает данные из базы данных. Этот метод должен выглядеть так:

public void readData(MyCallback myCallback) {
    databaseReference.child(String.format("users/%s/name", uid)).addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            String value = dataSnapshot.getValue(String.class);
            myCallback.onCallback(value);
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {}
    });
}

. В конце просто просто вызовите метод readData() и передайте экземпляр интерфейса MyCallback в качестве аргумента везде, где вам это нужно:

readData(new MyCallback() {
    @Override
    public void onCallback(String value) {
        Log.d("TAG", value);
    }
});

Это единственный способ, которым вы можете использовать это значение вне метода onDataChange(). Для получения дополнительной информации вы также можете посмотреть это видео .

2
задан mKorbel 16 April 2013 в 21:07
поделиться