getContactsFromFirebase() 方法返回一个空列表

2023-11-26

public List<String> getContactsFromFirebase(){
    FirebaseDatabase.getInstance().getReference().child("Users")
            .addListenerForSingleValueEvent(new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {
                    for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
                        Users user = snapshot.getValue(Users.class);
                        assert user != null;
                        String contact_found = user.getPhone_number();
                        mContactsFromFirebase.add(contact_found);
                        Log.i("Test", mContactsFromFirebase.toString());
                    }

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

    return mContactsFromFirebase;

}

我似乎找不到错误。在上面的代码中,当我调用日志时,我从以下位置获取值mContactsFromFirebase,但是getContactsFromFirebase()方法返回一个空列表。请问你能帮帮我吗?


数据从 Firebase 异步加载。由于从服务器获取数据可能需要一些时间,因此主要的 Android 代码将继续,Firebase 会调用您的onDataChange当数据可用时。

这意味着当您return mContactsFromFirebase它仍然是空的。查看此情况的最简单方法是放置一些日志语句:

System.out.println("Before attaching listener");
FirebaseDatabase.getInstance().getReference().child("Users")
    .addListenerForSingleValueEvent(new ValueEventListener() {
      @Override
      public void onDataChange(DataSnapshot dataSnapshot) {
        System.out.println("In onDataChange");
      }
      @Override
      public void onCancelled(DatabaseError databaseError) {
        throw databaseError.toException(); // don't ignore errors
      }
    });
System.out.println("After attaching listener");

当您运行此代码时,它将打印:

在附加监听器之前

附加监听器后

在 onDataChange 中

这可能不是您期望的输出顺序。正如您所看到的行after回调之前被调用onDataChange。这解释了为什么您返回的列表是空的,或者(更正确地)当您返回它时它是空的并且稍后才会被填充。

有几种方法可以处理这种异步加载。

最简单的解释就是把所有返回列表的代码放在一起into the onDataChange方法。这意味着该代码仅在数据加载后执行。最简单的形式:

public void onDataChange(DataSnapshot dataSnapshot) {
    for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
        Users user = snapshot.getValue(Users.class);
        assert user != null;
        String contact_found = user.getPhone_number();
        mContactsFromFirebase.add(contact_found);
        System.out.println("Loaded "+mContactsFromFirebase.size()+" contacts");
    }
}

但还有更多方法,包括使用自定义回调(类似于 Firebase 自己的ValueEventListener):

Java:

public interface UserListCallback {
  void onCallback(List<Users> value);
}

Kotlin:

interface UserListCallback {
  fun onCallback(value:List<Users>)
}

现在您可以将此接口的实现传递给您的getContactsFromFirebase method:

Java:

public void getContactsFromFirebase(final UserListCallback myCallback) {
  databaseReference.child(String.format("users/%s/name", uid)).addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
      for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
        Users user = snapshot.getValue(Users.class);
        assert user != null;
        String contact_found = user.getPhone_number();
        mContactsFromFirebase.add(contact_found);
        System.out.println("Loaded "+mContactsFromFirebase.size()+" contacts");
      }
      myCallback.onCallback(mContactsFromFirebase);
    }

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

Kotlin:

fun getContactsFromFirebase(myCallback:UserListCallback) {
  databaseReference.child(String.format("users/%s/name", uid)).addListenerForSingleValueEvent(object:ValueEventListener() {
    fun onDataChange(dataSnapshot:DataSnapshot) {
      for (snapshot in dataSnapshot.getChildren())
      {
        val user = snapshot.getValue(Users::class.java)
        assert(user != null)
        val contact_found = user.getPhone_number()
        mContactsFromFirebase.add(contact_found)
        System.out.println("Loaded " + mContactsFromFirebase.size() + " contacts")
      }
      myCallback.onCallback(mContactsFromFirebase)
    }
    fun onCancelled(databaseError:DatabaseError) {
      throw databaseError.toException()
    }
  })

然后这样称呼它:

Java:

getContactsFromFirebase(new UserListCallback() {
  @Override
  public void onCallback(List<Users> users) {
    System.out.println("Loaded "+users.size()+" contacts")
  }
});

Kotlin:

getContactsFromFirebase(object:UserListCallback() {
  fun onCallback(users:List<Users>) {
    System.out.println("Loaded " + users.size() + " contacts")
  }
})

它不像同步加载数据那么简单,但是这样做的优点是它运行时不会阻塞主线程。

这个话题已经讨论过了a lot之前,所以我建议您也检查其中一些问题:

  • this 道格的博客文章
  • 在 Firebase Listener 中设置 Singleton 属性值(我解释了在某些情况下你如何can获得同步数据加载,但通常不能)
  • 返回一个对象 Android(我第一次用日志语句来解释发生了什么)
  • 是否可以从 Firebase 同步加载数据?
  • https://stackoverflow.com/a/38188683(Doug 展示了一种很酷但复杂的使用方法TaskAPI 与 Firebase 数据库)
  • 如何返回 DataSnapshot 值作为方法的结果?(我从那里借用了一些回调语法)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

getContactsFromFirebase() 方法返回一个空列表 的相关文章

随机推荐

  • 如何查找具有相同捆绑包标识符的多个应用程序?

    有谁知道 在文件系统中 查找具有给定包标识符的每个应用程序的好方法 NSWorkspace和启动服务可让您通过捆绑包标识符查找应用程序 但仅返回单个结果 我怀疑聚光灯 NSMetadataQuery 可能会有所帮助 但我对其 API 有点不
  • 如何使用 s3 中的预训练模型来预测某些数据?

    我已经使用 sagemaker 训练了语义分割模型 并且输出已保存到 s3 存储桶中 我想从 s3 加载这个模型来预测 sagemaker 中的一些图像 我知道如何预测训练后是否让笔记本实例继续运行 因为它只是一个简单的部署 但如果我想使用
  • 向 Python enum.IntEnum 添加属性和起始值

    如何定义一个以某种方式派生的 Python 枚举类int 具有自定义起始值 并添加自定义属性 我知道如何从中得出int using enum IntEnum并设置起始值 Goo enum IntEnum Goo MOO FOO LOO st
  • Keras:重塑以连接 lstm 和 conv

    这个问题作为一个问题而存在github问题 也 我想在 Keras 中构建一个神经网络 其中包含 2D 卷积和 LSTM 层 网络应对 MNIST 进行分类 MNIST中的训练数据是60000张手写数字0到9的灰度图像 每张图像都是28x2
  • Android 模拟器将 600x1024 MDPI 报告为 XLarge?

    我目前正在尝试测试现有应用程序与即将发布的 Amazon Kindle Fire 平板电脑的兼容性 他们说将模拟器设置为 600x1024 将 LCD 密度设置为 169 https developer amazon com help fa
  • Pandas DataFrames/Series 之间的大于/小于比较

    如何在 DataFrame 和 Series 之间进行比较 我想屏蔽 DataFrame Series 中大于 小于另一个 DataFrame Series 中的元素的元素 例如 以下内容不会替换大于平均值的元素 与 nans 一起 尽管我
  • ReactJS.NET MVC 教程不起作用?

    我正在尝试在 Visual Studio 中设置一个新项目 该项目将是 MVC 5 其中包含用 ReactJS 编写的单页应用程序 所以我跟着ReactJS 网站上的指南 我到达了运行项目的第一部分 由于 JSX 我遇到了语法错误 浏览器似
  • 毫无例外地处理 STL 错误

    我有一个项目大量使用STL 现在我正在努力将项目移植到不支持异常的特定平台 我可以禁用异常 但是我仍然需要处理 STL 错误 是否有任何方法可以在禁用异常的情况下正确处理 STL 错误 是否有任何第三方 STL 实现可以帮助解决这个问题 使
  • 获取 Javascript 变量类型的更好方法?

    在 JS 中是否有更好的方法来获取变量的类型typeof 当你这样做时它工作得很好 gt typeof 1 number gt typeof hello string 但当你尝试时它是无用的 gt typeof 1 2 object gt
  • 当前文件中未定义导出默认异步函数

    以下效果完美 export default function x return hello world export function y return x console log y 但这不起作用 export default async
  • 使用 CMake 查找 BLAS 包含目录

    在 CMake 中我使用find package BLAS REQUIRED 我用BLAS FOUND BLAS LINKER FLAGS BLAS LIBRARIES适当的变量 我的问题是 如何根据已选择的 BLAS 实现找到 CMake
  • 如何将 ActiveSupport::Configurable 与 Rails Engine 一起使用

    我想给我的轨道引擎宝石适当的配置可能性 看起来像这样的东西initializers my gem rb 链接到当前的初始化程序 MyGem configure do config config awesome var true config
  • DATEDIFF() 参数问题

    旧的 DATEDIFF 允许用户使用 3 个参数 我试图这样做 这样我就可以从 DATEDIFF 中获得几个小时而不是几天 我试图显示自发布以来的小时数 在我的数据库中 我使用时间戳和这行代码来提取值 显然它不起作用 因为我有额外的参数 一
  • 查找项目中某个dll的所有引用

    在 Visual Studio 2010 或 2012 中 有一种方法可以找到代码中提及引用的 dll 中定义的任何类 方法的所有引用 目前我使用两个流程 根据情况而定 第一个涉及从项目中删除 dll 引用 然后记下所有构建错误位置 另一种
  • 通过 Web API 发送的字符串用引号括起来

    我在 ASP NET 4 中使用 C 的 Web API 遇到了一个小问题 我正在尝试创建一个前端 GUI 它通过多个 Web API 发送和接收数据 拥有多个 API 的原因与我们的网络有关 该网络由多个安全区域组成 服务器放置在不同的区
  • WPF TextBox 触发器清除文本

    我有很多TextBox控件 我正在尝试编写一种样式清除文本财产when控制是disabled 我不想在代码后面有事件处理程序 我写了这个
  • 最小示例:从反应应用程序中打开电子窗口?

    假设我正在使用 React Redux 和 Electron 构建一个桌面应用程序 所以我在电子中的index html文件看起来像这样 div div 我最大的 React 容器 称为 app js 被加载到 id content div
  • 为什么多重递增/递减在 C++ 中有效,但在 C 中无效?

    测试 c cpp include
  • 从存储过程执行 SQL Server SSIS 包

    我有一个存储在 SQL Server 2005 DB 中的 SSIS 包 我正在尝试从同一服务器上的存储过程执行此包 有没有比 exec master xp cmdshell dtexec SQL 更好的方法 我遇到了 我认为 xp cmd
  • getContactsFromFirebase() 方法返回一个空列表

    public List