android - 从 firebase 查询数据

标签 android firebase firebase-realtime-database

我正在尝试从我的 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 事件,所以我的问题是......我怎样才能使这个方法返回来自数据库的项目列表?

最佳答案

当您调用 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;
}

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

Attaching listener

Returning 0 items

Received items

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

另请参阅:

关于android - 从 firebase 查询数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43576441/

相关文章:

c - 如何在ContinueWith Firebase auth UNITY3D中更改游戏对象

安卓播放突然停止

android - 如何将我的 Android 手机屏幕投影到我的电脑显示器上?

firebase - 控制点 : Best approach for sending scheduled notification

javascript - Firebase - 检查数据是否有子项

ios - 如何以正确的方式从 firebase 数据库加载图像

android - Firebase 使用提供商帐户重置密码

android - 为什么项目上下文菜单没有显示在 ListView 中

Android数据存储性能

firebase - 一个应用程序实例可以在 FCM 中订阅多少个主题?