当前位置: 首页 > 知识库问答 >
问题:

Android Firebase:将同步功能转换为异步功能

颜功
2023-03-14

我正在做一个函数(Java-Android),它应该返回一个由Firebase中的数据填充的对象列表。我的问题是,我需要在遍历for中的所有项目后将结果发送给监听器,看看代码:

final DatabaseReference beaconMessageRef = dataSnapshot.getRef().getRoot().child("region_messages/" + regionKey);
beaconMessageRef.addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {

        if(!dataSnapshot.exists())
            FirebaseHelper.this.messageByBeaconListener.onSuccess(null);

        for (DataSnapshot regionMessageDS : dataSnapshot.getChildren()) {

            RegionMessage regionMessage = regionMessageDS.getValue(RegionMessage.class);
            String msgKey = regionMessageDS.getKey();

            final DatabaseReference messageRef = regionMessageDS.getRef().getRoot().child("messages/"+msgKey);
            messageRef.addListenerForSingleValueEvent(new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {

                    if(dataSnapshot.exists()){
                        Message msg = dataSnapshot.getValue(Message.class);
                        FirebaseHelper.this.addMessageByBeacon(msg);
                    }
                }

                @Override
                public void onCancelled(DatabaseError databaseError) {
                    FirebaseHelper.this.messageByBeaconListener.onFail(databaseError);
                }
            });
        }

        List<Message> msgs = FirebaseHelper.this.beaconMessageList;
        FirebaseHelper.this.beaconMessageList = null;
        FirebaseHelper.this.messageByBeaconListener.onSuccess(msgs);
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {
        FirebaseHelper.this.messageByBeaconListener.onFail(databaseError);
    }
});

我需要执行这一行:FirebaseHelper。这messageByBeaconListener。成功(msgs) 就在我循环浏览for中的所有项目之后。

我怎样才能做到这一点?


共有1个答案

水麒
2023-03-14

在Android系统上,异步的东西不能可靠地同步。每当你有这样做的冲动时,深呼吸,重复第一句话。或者在这里阅读我的答案:在Firebase监听器中设置Singleton属性值

相反,您必须做每个人都做的事情:将需要数据的代码移动到数据可用时触发的回调中。

在你的情况下,这有点棘手,因为你要加载多个项目。幸运的是,尽管你知道你需要加载多少项目。所以如果你引入一个计数器来跟踪加载了多少项目,你就会知道什么时候完成:

final DatabaseReference beaconMessageRef = dataSnapshot.getRef().getRoot().child("region_messages/" + regionKey);
beaconMessageRef.addListenerForSingleValueEvent(new ValueEventListener() {
  @Override
  public void onDataChange(DataSnapshot dataSnapshot) {
    if(!dataSnapshot.exists())
      FirebaseHelper.this.messageByBeaconListener.onSuccess(null);

    for (DataSnapshot regionMessageDS : dataSnapshot.getChildren()) {

      RegionMessage regionMessage = regionMessageDS.getValue(RegionMessage.class);
      String msgKey = regionMessageDS.getKey();

      final Integer[] counter = new Integer[1];
      final DatabaseReference messageRef = regionMessageDS.getRef().getRoot().child("messages/"+msgKey);
      messageRef.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot innerSnapshot) {
          if(innerSnapshot.exists()){
            Message msg = innerSnapshot.getValue(Message.class);
            FirebaseHelper.this.addMessageByBeacon(msg);
          }
          counter[0] = new Integer(counter[0].intValue()+1);
          if (counter[0].equalTo(dataSnapshot.numChildren()) {
            List<Message> msgs = FirebaseHelper.this.beaconMessageList;
            FirebaseHelper.this.beaconMessageList = null;
            FirebaseHelper.this.messageByBeaconListener.onSuccess(msgs);
          }
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
          FirebaseHelper.this.messageByBeaconListener.onFail(databaseError);
        }
      });
    }
  }

  @Override
  public void onCancelled(DatabaseError databaseError) {
    FirebaseHelper.this.messageByBeaconListener.onFail(databaseError);
  }
});

有关单元素数组的解释,请参见以下答案:https://stackoverflow.com/a/5977866/209103

 类似资料:
  • 我正在尝试做一个简单的应用程序,加载数据并对其执行一个操作.所以我的想法是做这个异步。 我有3个数据源,我想异步加载它们。例如data1.xml、data2.xml和data3.xml所有文件加载起来都相当大,所以需要一些时间(这就是为什么我想要异步的原因)。 例如,我创建了一个包含3个文本框的窗口,这些文本框都绑定到一个特定的属性(Text1、Text2、Text3)和一个按钮。当我点击按钮时,

  • 问题内容: 我是nodejs的新手,正在编写一些查询MySQL数据库并从给定的user_id返回用户名的代码。我一直在阅读,您所有的功能都应该是异步的。在这种情况下,理想情况下,我希望服务器能够在进行此查询时响应其他事件请求。但是,这不是一个特别大的查询,只返回一个值。也许我应该使其同步?(如果这是您的答案,那么更改示例代码将是不错的选择)无论如何,这是我的功能。它在最后一行“ return cu

  • 我们使用通道来同步协程之间的执行。 下面的例子是通过获取同步通道数据来阻塞程序执行的方法来等待另一个协程运行结束的。 也就是说main函数所在的协程在运行到<-done语句的时候将一直等待worker函数所在的协程执行完成,向通道写入数据才会(从通道获得数据)继续执行。 package main import "fmt" import "time" // 这个worker函数将以协程的方式运行 /

  • 问题内容: 之间有什么区别 和 如果我错了,请忽略此问题。 问题答案: 在第一个线程中,只有一个线程一次可以执行整个方法,而在第二个线程中,如果不将 其 用作参数,则只有一个线程可以执行该同步块。 这是它的副本。使用同步方法而不是同步块是否有优势?

  • 问题内容: 我可以使用关键字将javascript函数标记为“异步”(即返回承诺)。像这样: 箭头功能的等效语法是什么? 问题答案: 异步 箭头函数 如下所示: 传递给它的 单个参数的 异步 箭头函数 如下所示: __ 该 匿名 形式的作品,以及: 异步函数 声明 如下所示: 在 回调中 使用异步函数:

  • 问题内容: 最近,我不得不更正Web应用程序(我没有创建)中的安全性问题。安全问题是,它正在使用非仅限HTTP的cookie。因此,我不得不将session- cookie设置为仅http-,这意味着您无法再从javascript中读取(设置)cookie的值。到目前为止,接缝都很容易。 更深层的问题是,使用的Web应用程序 在一百万个地方 。 因此,为了不必重写“一百万行代码”,我不得不创建一个