2016-09-13 41 views
0
public class DataService { 

    private static DataService ourInstance = new DataService(); 
    private DatabaseReference mDatabase; 


    public static DataService getInstance() { 
     return ourInstance; 
    } 

    public ArrayList<UserDatabase> getFriendList() { 

     mDatabase = FirebaseDatabase.getInstance().getReference().child("users"); 
     final ArrayList<UserDatabase> list = new ArrayList<>(); 

     mDatabase.addChildEventListener(new ChildEventListener() { 
      @Override 
      public void onChildAdded(DataSnapshot dataSnapshot, String s) { 
       UserDatabase userDatabase = dataSnapshot.getValue(UserDatabase.class); 
       list.add(userDatabase); 
      } 

      @Override 
      public void onChildChanged(DataSnapshot dataSnapshot, String s) {} 

      @Override 
      public void onChildRemoved(DataSnapshot dataSnapshot) {} 

      @Override 
      public void onChildMoved(DataSnapshot dataSnapshot, String s) {} 

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

     return list; 
    } 
} 

我試圖從users節點獲取我的用戶數據庫。這真的很奇怪。當我在onChildAdded函數中設置斷點時,它將檢索所有用戶並將其添加到列表中。ArrayList不在內部更新onChildAdded函數

但是,如果我沒有設置斷點,它沒有得到任何東西,列表大小爲0.有沒有人知道發生了什麼?提前致謝!

+0

但隨後它可能再被稱爲和覆蓋。你不能將'list'移動到一個字段嗎? –

+0

我不認爲它被覆蓋。當我在所有進程之後的返回列表中設置一個斷點時,它將返回正確的數據。但如果不是的話,它甚至不會去onChildAdded函數 –

+0

我並不真正熟悉android/firebase,但是什麼時候被監聽器調用? –

回答

5

數據從Firebase異步加載並同步。

這是最簡單的,看看是什麼導致你的問題,如果你添加了一些有利的位置記錄語句:

public ArrayList<UserDatabase> getFriendList() { 

    mDatabase = FirebaseDatabase.getInstance().getReference().child("users"); 
    final ArrayList<UserDatabase> list = new ArrayList<>(); 

    System.out.println("Attaching listener"); 
    mDatabase.addChildEventListener(new ChildEventListener() { 
     @Override 
     public void onChildAdded(DataSnapshot dataSnapshot, String s) { 
      System.out.println("Got data"); 
     } 

     public void onChildChanged(DataSnapshot dataSnapshot, String s) {} 
     public void onChildRemoved(DataSnapshot dataSnapshot) {} 
     public void onChildMoved(DataSnapshot dataSnapshot, String s) {} 
     public void onCancelled(DatabaseError databaseError) {} 
    }); 

    System.out.println("Returning list"); 
    return list; 
} 

輸出將順序打印:

附加監聽

返回列表

有數據

這可能不是您所期望的順序。但它確實解釋了爲什麼如果按原樣運行代碼,則爲空列表。

原因是Firebase異步加載和同步數據。像大多數現代Web API一樣,它不會等待結果返回(這會導致可怕的用戶體驗),而是讓程序繼續並在獲取(新)數據時回調您的代碼。

處理這種行爲的方法是將程序的流程從「首先獲取朋友列表,然後用xyz做起」重新構建到「每當朋友列表發生變化時,用xyz做它」。

例如說你只是想打印有多少朋友。您當前的方法可能是:

ArrayList<UserDatabase> friends = getFriendList(); 
System.out.println("There are "+friends.size()+" friends"); 

隨着火力地堡一個處理這種方式是將操作getFriendList()

public void getFriendList() { 

    mDatabase = FirebaseDatabase.getInstance().getReference().child("users"); 
    final ArrayList<UserDatabase> list = new ArrayList<>(); 

    mDatabase.addChildEventListener(new ChildEventListener() { 
     @Override 
     public void onChildAdded(DataSnapshot dataSnapshot, String s) { 
      UserDatabase userDatabase = dataSnapshot.getValue(UserDatabase.class); 
      list.add(userDatabase); 
      System.out.println("There are "+friends.size()+" friends"); 
     } 

     public void onChildChanged(DataSnapshot dataSnapshot, String s) {} 
     public void onChildRemoved(DataSnapshot dataSnapshot) {} 
     public void onChildMoved(DataSnapshot dataSnapshot, String s) {} 
     public void onCancelled(DatabaseError databaseError) {} 
    }); 

} 
+0

有一個[新問題](http://stackoverflow.com/q/39518283/4815718),實質上是這個問題的一個重複。我回答並提供了一個鏈接。如果你願意,可以自由地將新的問題作爲一個副本來解決。 –