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

Firestore OncompleteListener[重复]

傅英喆
2023-03-14

我想看看这段代码中的错误是什么,当我编译它时,它只返回log1,3,2的值,我希望log2在3之前

Log.d("1", "antes de validar");
    DocumentReference docRef = db.getDb().collection("Usuarios").document(Correo);
    docRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
        @Override
        public void onComplete(@NonNull Task<DocumentSnapshot> task) {
            Log.d("2", "validar");
            if (task.isSuccessful()) {
                DocumentSnapshot document = task.getResult();
                if (document.exists()) {
                    setBanderaValidarCorreoDB(true);
                    return;
                } else {
                    setBanderaValidarCorreoDB(false);
                    return;
                }
            } else {
                Toast.makeText(contextoRegistro, "ERROR al Realizar la validacion de Correo"+ task.getException(), Toast.LENGTH_SHORT).show();
                setBanderaValidarCorreoDB(false);
                return;
            }
        }
    });
    Log.d("3", "despues de validar");
    return BanderaValidarCorreoDB;
}

这就是它的表现

07-08 13:47:56.968 6027-6027/felipe.monumentosfinalcertamen D/1: antes de 
 validar
07-08 13:47:56.980 6027-6027/felipe.monumentosfinalcertamen D/3: despues de validar
07-08 13:47:57.071 6027-6052/felipe.monumentosfinalcertamen W/EGL_emulation: eglSurfaceAttrib not implemented
07-08 13:47:57.071 6027-6052/felipe.monumentosfinalcertamen W/OpenGLRenderer: Failed to set EGL_SWAP_BEHAVIOR on surface 0xe2b2a700, error=EGL_SUCCESS
07-08 13:47:57.149 6027-6052/felipe.monumentosfinalcertamen W/EGL_emulation: eglSurfaceAttrib not implemented
07-08 13:47:57.149 6027-6052/felipe.monumentosfinalcertamen W/OpenGLRenderer: Failed to set EGL_SWAP_BEHAVIOR on surface 0xe2cf7540, error=EGL_SUCCESS
07-08 13:47:57.177 6027-6052/felipe.monumentosfinalcertamen V/RenderScript: 0xeff9b600 Launching thread(s), CPUs 4
07-08 13:47:58.483 6027-6027/felipe.monumentosfinalcertamen D/2: validar
07-08 13:52:35.654 6027-6068/felipe.monumentosfinalcertamen I/FirebaseAuth: [FirebaseAuth:] Loading module via FirebaseOptions.
    [FirebaseAuth:] Preparing to create service connection to gms implementation

共有1个答案

谷梁翰飞
2023-03-14

数据是异步加载的。当您的返回BanderaValidarCorreoDB时,数据还没有加载。没有办法让返回语句等待数据加载。这是设计好的,我强烈建议尽早接受针对异步API的编程。

解决方案可以是两件事之一:

  1. 将需要数据的代码移动到onComplete

将需要数据的代码移动到onComplete是最简单的方法。这类似于您已经调用setBanderaValidarCorreoDB,但也调用了需要BanderaValidarCorreoDB值的代码:

public void onComplete(@NonNull Task<DocumentSnapshot> task) {
    if (task.isSuccessful()) {
        DocumentSnapshot document = task.getResult();
        if (document.exists()) {
            setBanderaValidarCorreoDB(true);
        } else {
            setBanderaValidarCorreoDB(false);
        }
    } else {
        Toast.makeText(contextoRegistro, "ERROR al Realizar la validacion de Correo"+ task.getException(), Toast.LENGTH_SHORT).show();
        setBanderaValidarCorreoDB(false);
    }
    doSomethingWithBanderaValidarCorreoDB(BanderaValidarCorreoDB);
}

这很简单,但是稍微减少了助手函数的重用。所以你也可以定义你自己的接口,并把它传递到你的助手函数中回调。代码可能比这里的单词更容易理解,所以:

public interface BanderaValidarCorreoDBCallback {
  void onCallback(boolean value);
}
void getBanderaValidarCorreoDB(BanderaValidarCorreoDBCallback callback)
    DocumentReference docRef = db.getDb().collection("Usuarios").document(Correo);
    docRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
        @Override
        public void onComplete(@NonNull Task<DocumentSnapshot> task) {
            if (task.isSuccessful()) {
                DocumentSnapshot document = task.getResult();
                if (document.exists()) {
                    setBanderaValidarCorreoDB(true);
                    return;
                } else {
                    setBanderaValidarCorreoDB(false);
                    return;
                }
            } else {
                Toast.makeText(contextoRegistro, "ERROR al Realizar la validacion de Correo"+ task.getException(), Toast.LENGTH_SHORT).show();
                setBanderaValidarCorreoDB(false);
                return;
            }
            callback(BanderaValidarCorreoDB);
        }
    });
}

然后你调用它作为:

getBanderaValidarCorreoDB(new BanderaValidarCorreoDBCallback() {
  @Override
  public void onCallback(boolean value) {
    System.out.println("Loaded "+value)
  }
});

对于不熟悉异步编程的开发人员来说,这是一个非常常见的困惑源。因此,我还建议您查看以下其他来源:

  • 如何检查firestore中是否存在特定数据
  • 在Firebase Listener中设置Singleton属性值(这也表明等待有时是可能的,但在Android上不可靠)
  • getContactsFromFirebase()方法返回一个空列表
  • Android:在服务类的第一次初始化期间从Firebase获取Pojo列表
  • Doug关于异步API的精彩博文

虽然其中许多是针对Firebase实时数据库的,但所有技术的问题和解决方案都是相同的。

 类似资料:
  • 嗨,我想知道是否有人能帮我。我有两个。xsd架构文件顺序服务顺序。xsd和order。xsd,每个xsd都将元素类型命名为“order”。 当我开始为这些模式文件创建Java源代码时,我显然在Order类上遇到了类名冲突。 我创建了一个jaxb bindings. xjb文件来重命名从orderservice-order.xsd.生成的订单类名 然而,我仍然得到以下错误 中的XPATH似乎没有问题

  • 上面说这是一次意外的超驰,但这不是偶然的... 我想要的可能吗?还是必须重写方法。我更喜欢kotlin setter..

  • 当我运行这段代码时,它会打印。我的问题是为什么没有编译时错误?对象和字符串的默认值为NULL。那么为什么不编译器说。

  • 也许我对概念感到困惑,但是重写和在子类中创建一个新方法之间有什么区别呢?重写不就是在子类中创建一个不同于父类的新的特定方法吗?但这难道不是在子类中创建一个新方法所要做的吗?

  • 我在一个有这些类的项目中工作: 这些coures类具有其他方法和属性。 如果可以的话,它应该能够使用来自Square和RedRectangle的方法,否则它应该使用来自Rectangle的方法,并且它应该迫使开发人员从他自己的代码中为所有在Square和RedRectangle中被重写的方法编写代码。 我实际上知道这是多重继承,Java不支持它,但我需要实现这种行为。 我试图使用Square和Re

  • 简介 本章中我会介绍重复。通过重复,你可以编写“通常的”程序。虽然也可以使用do表达式,但Scheme中通常通过递归实现重复。 递归 在自己的定义中调用自己的函数叫做递归函数(Recursive Function)。虽然这听起来很奇怪,但是循环的常见方法。如果你把函数类比为机器的话,递归似乎毫无道理。然而,正因为函数是过程,函数调用自己是有意义的。比如说,让我们来考察一下文献调研吧。你可能需要去阅

  • 问题内容: 这个问题已经在这里有了答案 : 8年前关闭。 可能重复: mysql中id(auto_increment列)的碎片 我的数据库中有此列。假设其名称为“ threadid”。它包含赋予每个线程以区别的唯一ID。 线程号9 8 7 6 5 4 3 2 1 假设我已删除ID为5和6的线程。 线程号9 8 7 4 3 2 1 但是,当删除后有一个提交时,给该线程的唯一ID是10。不是5。我认为

  • 我正在尝试重命名/删除一个 Mongo 集合,我无意中放了一个 .(点) 在数据库集合名称的末尾,因此集合名称如下所示: 收藏品名称。 我无法找到一种方法来使用包含点号的集合名称来删除或重命名集合,而不会返回错误。 任何建议这是否是可能的。