이것은 비동기 웹 API의 고전적인 문제입니다. 아직로드되지 않은 것을 반환 할 수 없습니다. 다른 말로하면, 글로벌 변수를 단순히 생성하여 이 될 것이므로 onDataChange()
메소드 밖에서 사용할 수 없습니다. 이것은 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!");
}
, 출력은 줘야 :
이 아마 청취자에게
있어 데이터
를 부착 한 후 청취자
를 장착하기 전에 당신이 기대 한 것이 아니지만, 당신의 d ata si 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()
메서드 밖에서 그 값을 사용할 수있는 유일한 방법입니다. 자세한 내용은 video을 참조하십시오. 당신은 캔트 ANW 곳
수익을 자사의 무효 방법 당신은 당신이 내부에 추가 외부 쓴 어떤 방법 때문에 어디서든 바로 onDataChange 내에서 사용이 변수를 사용하려면 또한 비동기 sooo를, 일을 못해 .. 반환하지 않습니다 의미 onDataChange –
언급 된 @PeterHaddad처럼 onDataChange 메서드는 비동기 적이므로 항상 null을 반환합니다. 나는 묻는다 : 당신은 왜 사용자 이름을 돌려 줄 필요가 있는가? 왜이 이름을 onDataChange 내에서 사용하지 않는가? –
@PeterHaddad는'onDataChange()'메소드가 비동기라고 불리기 때문에 작동하지 않을 것이라고 말했다. 내 대답을 참조하십시오. –