0

Firebase로 Android에서 작업하고 있습니다. 데이터베이스의 arrayAdapter에 정보 목록을 표시하려고합니다. 나는 Url의 ArrayList를 사용하고 있습니다. 과 같이 구조화 비정규 중포 기지 데이터베이스에서 일부 사용자 정보를 가져올 수 :ArrayAdapter를 사용하여 여러 Firebase 데이터베이스 참조에서 가져온 데이터를 표시합니다.

name : { 
uid1:"bear", 
uid2:"salmon" 
}, 

phone : { 
uid1:"888-395-4023", 
uid2:"123-456-6789" 
} 

내 현재의 접근 방식은이 같은 클래스의 사용자 정보 객체로 가져온 값을 저장하는 것입니다.

public UserInfo (String name, String phone) 

각 개체를 arrayAdapter에 추가하십시오.

someArrayAdapter.add(userInfo); 

내 문제는 둘 이상의 사용자와, 그리고 이벤트 리스너 콜백이 추가 이후에 접수되기 때문에 추가 된 사용자 정보에서 내 다음 구현에서, 하나 이상의 참조에서 데이터를 읽는 모든 필드() 메소드 비어 있습니다 전화 (콜백이 수신 될 때 데이터가 업데이트되지 않습니다) 난에 대한 루프는 다음 UID으로 진행하기 전에 "완전한"사용자 정보 객체를 갖고 싶어

private FirebaseDatabase mFirebaseDatabase = new FirebaseDatabase.getInstance(); 
private ValueEventListener mNameListener; 
private ValueEventListener mPhoneListener; 
private DatabaseReference mNameRef; 
private DatabaseReference mPhoneRef; 

private void getUserInfo (@NonNull final ArrayList<String> uidList) 
{ 
    // This for-loop loops through the list of strings, and use the string to construct new database references. 

    for (String uid : uidList) 
    { 
      // Create a new userInfo object 
      UserInfo userInfo = new UserInfo(); 

      // Create a database reference for accessing the name 
      mNameRef = mFirebaseDatabase.getReference().child("name").child(uid); 

      // Create a database reference for accessing the name 
      mPhoneRef = mFirebaseDatabase.getReference().child("phone").child(uid); 

      // My name listener 
      mNameListener = new ValueEventListener() 
      { 
       @Override 
       public void onDataChange(final DataSnapshot dataSnapshot) { 
        String name = DataSnashot.getValue().toString(); 
        userInfo.setName(name); 
       } 
       // ...skipped irrelevant override 
      } 

      // My phone listener 
      mPhoneListener = new ValueEventListener() 
      { 
       @Override 
       public void onDataChange(final DataSnapshot dataSnapshot) { 
        String phone = DataSnashot.getValue().toString(); 
        userInfo.setPhone(phone); 

        // Log to try getting the phone from the object, as expected, is good 
        Log.i(TAG, userInfo.getPhone()); 
       } 
       // ...skipped irrelevant override 
      } 

      // Attach the listeners 
      mNameRef.addListenerForSingleValueEvent(mNameListener); 
      mPhoneRef.addListenerForSingleValueEvent(mPhoneListener); 

      // Problem here: listener callbacks are received after this method fires. 
      someArrayAdapter.add(userInfo); 

      // Log, returns empty for both fields, and this log message runs before the callback log messages above. 
      Log.i(TAG, userInfo.getName() + " " + userInfo.getPhone()); 

    } 
} 

. 그리고 모든 콜백을받은 경우에만 어댑터가 userInfo 객체를 추가하도록 어떻게 관리해야합니까?

데이터를 영구적으로 만드는 더 좋은 방법이 필요하지만, 단순한 개체 만 처리 할 수 ​​있다면 관리가 훨씬 쉬워집니다. 귀하의 도움과 시간을 보내 주셔서 감사 드리며 어떠한 구문이나 누락에 대해 용서해주십시오. ";" 문제, 내가 IDE에서 샘플 코드를 작성하지 않았다 :)

답변

1

다행히 콜백은 발생하지만 비동기입니다. 즉, Firebase가 별도의 스레드에서 실행되기 때문에 for 루프가 시작될 때 초기화 한 기본 스레드의 userinfo 객체가 즉시 추가됩니다.

UserInfo userInfo = new UserInfo(); 
    ..ASYNC FIREBASE CODE 
    someArrayAdapter.add(userInfor); 

firebase 콜백은 비동기 적이므로 자신의 스레드에서 실행되므로 사용자 정보가 즉시 추가됩니다. userInfo에는 현재 정보가 없으므로 본질적으로 빈 사용자 정보 객체가 추가됩니다.

원하는대로이 작업을 수행 할 수 있습니다. 콜백 내부에 사용자 정보 객체를 추가합니다.

mNameListener = new ValueEventListener() 
     { 
      @Override 
      public void onDataChange(final DataSnapshot dataSnapshot) { 
       String name = DataSnashot.getValue().toString(); 
       userInfo.setName(name) 
       // Here you make a new event listner 

       mPhoneRef.addSingleValueEventListener(new ValueEventListener(){ 

    onDataChange(DatasnapShot datasnapshot){ 
    String phone = DataSnashot.getValue().toString(); 
    userInfo.setPhone(phone); 
    someAdapater.add(userInfo); // add your user info here 
    } 

    mNameRef.addListenerForSingleValueEvent(mNameListener); 

    //someArrayAdapter.add(userInfor); // Do not have this here anymore 

첫 번째 청취자 내부에서 다른 청취자를 첨부하여 전화 번호를 가져옵니다. 일단 값이 있으면 어댑터에 추가하십시오.

그러나 데이터베이스 디자인을 다시 고려해야합니다. 데이터베이스가 매우 비효율적입니다. 추가 쿼리를 할 필요가 없으며 추가 쿼리를 작성하면 안됩니다. UserInfo 객체를 하나의 노드 아래에 밀어 넣고 원하는대로 검색해야합니다.

이 작업을 수행 할 수있는 방법의 예는 다음 푸시 키를

UserInfo userinfo = new UserInfo("Name","133405-333") 
root.child("userInfo").push().setValue(userInfo); 

를 사용하는 대신 정보를 분리하여, 당신은 하나 개의 노드에서 모든 것을 넣어. 이것은 데이터베이스의 다른 부분을 쿼리 할 필요없이 특정 쿼리를 작성할 수있는 많은 데이터베이스 구조입니다.

+0

의견을 주셔서 감사합니다. 그러나 귀하의 접근 방식이 규모에 맞지 않을 것이라고 생각합니다.데이터베이스 구조에 관해서는 Firebase 문서의 비정규 화에 따른 모범 사례를 따르고 있습니다. 내 실제 데이터베이스에는 14 개의 사용자 필드가 있습니다. 모든 정보를 함께 뒤섞어 놓으면 uid와 일치하는 정보가 단 하나의 정보로 채워지는 쿼리가 매우 오래 걸릴 것입니다. –

+0

표시된 구조가 주어졌지만 사용자가 이름이 없지만 전화 번호가있는 경우에는 어떻게됩니까? 전화 수신기와 이후에 someAdapater가 전혀 실행되지 않습니다. –

+0

그래도 괜찮습니다. firebase는 스키마가 적기 때문에. 당신은 이것을 할 수 있습니다. Userinfo userinfo = 새 UserInfo (이름). 그냥 이름을 사용하는 생성자를 가지고 있고 동일한 노드 아래에 해당 사용자 정보를 넣을 수 있습니다. –