0

我正在使用Firebase的Android工作。我想用數據庫中的arrayAdapter顯示信息列表。我正在使用uid的ArrayList。從結構化的,就像這樣規格化火力數據庫中獲取一些用戶信息:使用arrayAdapter顯示從多個Firebase數據庫引用獲取的數據

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

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

我目前的做法是將所獲取的值存儲到這樣一個類的對象的UserInfo。

public UserInfo (String name, String phone) 

然後將每個對象添加到arrayAdapter。

someArrayAdapter.add(userInfo); 

我的問題是有一個以上的用戶,因爲事件偵聽器回調的添加後,收到了來自超過一個參考讀取數據,我在下面的實現都在增加用戶信息字段爲空()方法調用(當接收到回調不更新數據)

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()); 

    } 
} 

我想擁有一個「完整的」用戶信息對象for循環去到下一個UID之前。而且,我應該如何管理,以便只有在接收到所有回調的情況下,適配器纔會添加userInfo對象?

我絕對需要一種更好的方式來使數據持久化,但就目前而言,如果我只能處理簡單的對象,我覺得維護更容易。感謝您的幫助和時間,請原諒我的任何語法或缺失「;」問題,我沒有寫在IDE上的示例代碼:)

回答

1

幸運的是,回調觸發,但它們是異步的。這意味着您在for循環開始時初始化的主線程上的userinfo對象會立即添加,因爲Firebase在單獨的線程上運行。

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

給出如圖所示的結構,但如果用戶沒有名稱,但有電話號碼會怎麼樣?電話聽衆和隨後的某些Adapater根本不會被觸發 –

+0

這還是很好的。由於firebase的模式較少。你可以這樣做。用戶信息用戶信息=新用戶信息(名稱)。只需要一個構造函數,只需使用該名稱,並且仍然可以將該用戶信息放在同一節點下 –

相關問題