Firebase 回调在测试期间有效,但在运行时无效

lhk

我在 Android 应用中使用 Firebase。该应用程序设置了类似群聊的功能,并允许用户加入。用户获得一个密钥,然后可以将自己连接到相应的 DatabaseReference。我们需要检查密钥是否有效。因此,在创建组时,主机会自动将自己添加到用户列表中。然后所有新客户端都可以检查列表中是否有条目。如果列表为空,则密钥无效。

这意味着我需要等待 setValue 调用完成。Firebase 有很多回调可以告诉我这个,但它们是相当有问题的。有时,他们根本就没有被调用。我已经在这里问了一个关于这种非确定性行为的问题:How to listen for Firebase setValue completion

现在我发现这些回调有一个新问题。我已将我的基础结构更改为异步设置。所有交互都打包到 Callables 中并提交给 ExecutorService。结果是一个 Future<>。现在,如果我想等待某事完成,我可以等待那个未来。在 Future 中,我仍然需要使用 Firebase 回调。

该代码位于称为 DBConnection 的包装类中。

这是我创建新组(派对)的代码:

public Future<DBState> createParty() {
    // assert entries
    assertState(DBState.SignedIn);

    // process for state transition
    Callable<DBState> creationProcess = new Callable<DBState>() {
        @Override
        public DBState call() throws Exception {

            lock.lock();
            try {
                // create a new party
                ourPartyDatabaseReference = partiesDatabaseReference.push();
                usersDatabaseReference = ourPartyDatabaseReference.child("users");

                // try every remedy for the missing callbacks
                firebaseDatabase.goOnline();
                ourPartyDatabaseReference.keepSynced(true);
                usersDatabaseReference.keepSynced(true);

                // push a value to the users database
                // this way the database reference is actually created
                // and new users can search for existing users when they connect

                // we can only continue after that task has been completed
                // add listeners for success and failure and wait for their completion

                // TODO: we need information that this task has been finished
                // but no callback seems to work
                // onSuccess, onCompletion on the task are not reliable
                // and the child and value event listeners on the userDatabaseReference are not reliable, too
                final CountDownLatch waiter = new CountDownLatch(1);
                usersDatabaseReference.addValueEventListener(new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {
                        waiter.countDown();
                    }

                    @Override
                    public void onCancelled(DatabaseError databaseError) {
                        waiter.countDown();
                    }
                });
                Task addingTask = usersDatabaseReference.child(user.getUid()).setValue(true);
                addingTask.addOnSuccessListener(new OnSuccessListener() {
                    @Override
                    public void onSuccess(Object o) {
                        waiter.countDown();
                    }
                });
                addingTask.addOnCompleteListener(new OnCompleteListener() {
                    @Override
                    public void onComplete(@NonNull Task task) {
                        waiter.countDown();
                    }
                });
                try {
                    waiter.await();
                } catch (InterruptedException ex) {
                }
                connectToParty();
            } finally {
                lock.unlock();
            }

            // if we could connect, we are now DBState.Connected,
            // otherwise we are still DBState.SignedIn
            return state;
        }
    };

    // start process
    return executorService.submit(creationProcess);

}

你可以这样使用它:

    Future<DBState> creationFuture = dbConnection.createParty();

    try {
        creationFuture.get(TIMEOUT, TimeUnit.MILLISECONDS);
    } catch (InterruptedException ex) {
        throw new AssertionError("there should be no interrupt");
    }catch (TimeoutException ex) {
        throw new AssertionError("timeout in party creation");
    }catch (ExecutionException ex) {
        throw new AssertionError("concurrent execution exception");
    }

我已经为此编写了测试。在测试中,一切正常。canCreateParty现在至少执行了十几次测试。

为了确保回调有效,我CountDownLatch将 计数增加到 3 并在countDowns. 每一个countDown都达到了。

但是在运行时,不会调用任何回调。没有到达断点,等待未来最终超时。

最奇怪的部分是:我在模拟器旁边打开了 firebase 控制台。我可以看到如何创建新方和添加用户。无论是在测试还是在运行时,派对创建都按预期工作,并添加了一个新用户。为什么我在运行时没有收到回调?

lhk

原因是 Firebase 总是从主线程调用它的回调。

我的测试中的“主”线程被称为“junittestrunnerXXX”之类的东西。Firebase 创建一个名为“main”的新线程来调用回调。

在运行时,“主”线程是实际的“主”线程。如果我调用 get() ,它就会被永久阻止。Firebase 检查此线程是否存在,并且由于它已经存在并且由于它被阻止,因此没有任何反应。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

代码在F8单步执行期间有效,但在运行时无效

程序在逐步执行时有效,但在运行时无效

putItem(itemRequest)在JUnit测试期间有效,但在AWS Lambda控制台上的测试期间无效

为什么我的 vba 脚本在逐行执行时(在调试中)有效,但在运行时无效?

VBA 在运行时崩溃,但在单步执行时有效

Firebase 功能在模拟器中有效,但在浏览器中无效

Firebase安全规则在模拟器中有效,但在代码中无效

Firebase Cloud 消息在模拟器中有效,但在 IOS 设备上无效

在运行时选择Firebase数据库

Firebase依赖项在运行时导致错误

窗口化在 DirectRunner 上运行时似乎有效,但在 Cloud Dataflow 上运行时无效

Firebase运行时崩溃

当应用程序在后台运行时获取Firebase通知(仅使用REST客户端的数据有效负载)

CRC32 校验和在运行时和 JUnit 测试期间不同

声明在编译时有效,但在运行Mocha测试时无效

Firebase部署| 您需要启用JavaScript才能运行此应用。| “ npm start”有效,但“ firebase serve”无效

angular2打字稿未编译,但在运行时有效

命令在脚本(或-c)中有效,但在直接运行时(在交互式shell中)则无效

代码在脚本编辑器中有效,但在从命令行运行时无效

运行时错误更新Firebase数据

Angular测试在单独运行时有效,但在与其他Tet一起运行时会失败

从Fabric Crashlytics更新后,Firebase Crashlytics在运行时崩溃

firebase firestore在运行时更新变量嵌套数据

在javascript中在运行时从firebase实时数据库动态获取数据

使用 Visual Studio 运行时查找和替换有效,但在运行 IIS 时出现空异常错误

使用SQL的Cosmos DB查询在Data Explorer中运行时有效,但在C#DocumentClient中执行时则无效

具有autoLayout的静态UITableViewCell的自动高度不会在IB中更新(但在运行时有效)

Aceess VBA-从网站获取数据的子例程在调试模式下有效,但在运行时不起作用

Firebase 规则 - 尽管“获取”请求有效(REST),但在 orderBy 查询中权限被拒绝