ArrayList不在onChildAdded函数内更新

0 java android firebase firebase-realtime-database

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;
     }
}
Run Code Online (Sandbox Code Playgroud)

我试图从users节点获取我的用户数据库.它的表现非常奇怪.当我在onChildAdded函数中设置断点时,它将检索所有用户并将其添加到列表中.

但是,如果我没有在那里设置断点,它没有得到任何东西,列表大小为0.有没有人知道发生了什么?提前致谢!

Fra*_*len 6

数据是从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;
 }
Run Code Online (Sandbox Code Playgroud)

输出将按以下顺序打印:

附加监听器

返回清单

得到了数据

这可能不是你预期的顺序.但它确实解释了为什么如果你按原样运行代码的空列表.

原因是Firebase异步加载和同步数据.像大多数现代Web API一样,它不会等待结果返回(这将导致可怕的用户体验),而是让程序继续并在获取(新)数据时回调您的代码.

处理这种行为的方法是重构你的程序流程,从"首先获取朋友列表,然后用它做xyz"到"每当朋友列表改变时,用它做xyz".

例如,假设您只想打印有多少朋友.您当前的方法可能是:

ArrayList<UserDatabase> friends = getFriendList();
System.out.println("There are "+friends.size()+" friends");
Run Code Online (Sandbox Code Playgroud)

使用Firebase,一种方法是将操作移动 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) {}
    });

 }
Run Code Online (Sandbox Code Playgroud)