从firebase查询数据

问题描述 投票:1回答:1

我想从我的firebase数据库中获取一个项目列表......但是我在获取它们时遇到了问题。我的代码看起来或多或少像这样:

List<Items> itemsList;

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_work_items_report);

    itemsList = GetItems();
}

并且应该返回我的项目的方法如下:

private ArrayList<Items> GetItems(){
    DatabaseReference database = FirebaseDatabase.getInstance().getReference();
    DatabaseReference ref = database.child("items");
    final ArrayList<Items> itemsRez = new ArrayList<Items>();
    Query itemsQuery = ref.orderByChild("type");

    itemsQuery.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            if (dataSnapshot.exists()) {
                for (DataSnapshot singleSnapshot : dataSnapshot.getChildren()) {
                    Items item = singleSnapshot.getValue(Items.class);
                    itemsRez.add(item);
                }
            }
        }
        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });
    return itemsRez;
}

GetItems()总是返回一个空列表,这有点意义,因为在返回此列表之前没有任何东西可以触发onDataChange事件,所以我的问题是...我怎么能让这个方法返回项目列表来自DB?

android firebase firebase-realtime-database
1个回答
3
投票

当您调用addListenerForSingleValueEvent()时,Firebase客户端开始从服务器加载数据,这可能需要一些时间。为了防止阻止您的应用程序(这将导致“应用程序无响应”对话框),它会在单独的线程中加载数据。因此,在加载数据时,您的主线程会继续并返回当前状态itemsRez,这是一个空列表。

如果在代码中添加一些日志语句,最简单的方法是:

private ArrayList<Items> GetItems(){
    DatabaseReference database = FirebaseDatabase.getInstance().getReference();
    DatabaseReference ref = database.child("items");
    final ArrayList<Items> itemsRez = new ArrayList<Items>();
    Query itemsQuery = ref.orderByChild("type");

    System.out.println("Attaching listener");
    itemsQuery.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            if (dataSnapshot.exists()) {
                for (DataSnapshot singleSnapshot : dataSnapshot.getChildren()) {
                    Items item = singleSnapshot.getValue(Items.class);
                    itemsRez.add(item);
                }
            }
            System.out.println("Received "+itemsRez.size()+" items");
        }
        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });
    System.out.println("Returning "+itemsRez.size()+" items");
    return itemsRez;
}

与您可能期望的相反,这将按此顺序打印日志记录:

附加监听器

返回0项

收到的物品

解决问题的一个常见解决方案是重新构建代码的目标。而不是写“先获取项目,然后用它们做abc”,将代码写为“开始获取项目。然后当它们进入时,用它们做abc”。在代码中,这意味着您将需要itemsRec的代码移动到onDataChange方法中,它将在适当的时刻调用:当项目已加载时。

另见:

© www.soinside.com 2019 - 2024. All rights reserved.