2016-09-13 15 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),实质上是这个问题的一个重复。我回答并提供了一个链接。如果你愿意,可以自由地将新的问题作为一个副本来解决。 –