在Java中使用Firebase,我的情况似乎从未调用Transaction.Handler.onComplete()
。
我试图等待特定事务的完成,所以我让调用线程继续前进,直到调用onComplete()
。这是由现有Transaction.Handler txn
周围的匿名装饰器完成的。
Transaction.Handler txn = ...
CountDownLatch latch = new CountDownLatch(1);
ref.runTransaction(new Transaction.Handler() {
@Override
public Transaction.Result doTransaction(MutableData data) {
return txn.doTransaction(data);
}
@Override
public void onComplete(FirebaseError e, boolean wasCommitted, DataSnapshot data) {
System.out.println("never printed");
txn.onComplete(e, wasCommitted, data);
if(e != null || !wasCommitted) {
System.out.println("error: " + e + ", committed: " + wasCommitted);
}
latch.countDown();
}
});
latch.await();
System.out.println("never printed");
doTransaction()
肯定至少完成一次 - 我可以在网络界面中看到数据更新 - 但onComplete()
永远不会被调用,我们只是挂起。
我无法看到此包装模式有任何问题:我在另一个Firebase上的测试main()
方法中单独运行相同的事务,并且onComplete()
打来电话。
导致此挂起的原因是什么? Firebase的配置(例如auth?规则?)是否存在一些在此引入错误的内容?
修改
我没有包装图案时遇到同样的问题。这是代码:
CountDownLatch latch = new CountDownLatch(1);
ref.runTransaction(new Transaction.Handler() {
@Override
public void onComplete(FirebaseError e, boolean b, DataSnapshot data) {
if(e != null || !b) {
System.out.println("error: " + e + ", committed: " + b);
}
System.out.println("transaction finished!");
latch.countDown();
}
@Override
public Result doTransaction(MutableData data) {
System.out.println("doing transaction");
data.child(...).setValue(...);
return Transaction.success(data);
}
});
latch.await();
System.out.println("never printed");
导致打印doing transaction
并且Firebase中的数据发生了变化(我通过网络用户界面看到),但不打印transaction finished
。它只是挂起。
答案 0 :(得分:4)
在Android上,所有Firebase回调都在主线程上运行。如果在主线程上调用latch.await()
,onComplete
将永远无法运行,因为主线程被阻塞,导致死锁。