1

我想从我的 Firebase 实时数据库中获取我的 wgID,它的值是 /WG/FlatNumber/ 现在这是我的代码:

主要活动:

System.out.println("1");
dbContact.schreibeFlatObjekt();
System.out.println("7");

schreibeFlat 对象:

//wgID is global
private String wgID;
public schreibeFlatObjekt(){
//CountDownLatch to wait for the Listener
final CountDownLatch cdl = new CountDownLatch(1);


    ValueEventListener listener = new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            System.out.println("3");
            //Getting the Data from the snapshot
            wgID = (String) dataSnapshot.getValue();
            System.out.println("4 wgID: " + wgID);
            //counting down the cdl so the cdl.await() can go on 
            cdl.countDown();

        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    };

    System.out.println("2");
    fref.child("WG").child("FlatNumber").addListenerForSingleValueEvent(listener);
    System.out.println("5");

    try{
        cdl.await();
    }
    catch(Exception e)
    {
        System.out.println(e.toString());
    }
    System.out.println("6 wgID: " +wgID);
    return 0;

所以当我不使用 CountdownLatch 时,System.out.println给我这个:

I/System.out: 1
I/System.out: 2
I/System.out: 5
I/System.out: 6 wgID: null
I/System.out: 7
I/System.out: 3
I/System.out: 4 wgID: 1

所以正如我所看到的,在方法已经准备好之后,监听器被执行。

如果我使用 CountDownLatch,它只会运行到“cdl.await()”,然后停止,监听器永远不会执行,应用程序也会停止。

那么如何获取我的 ID,我的意思是我只想要我的数据库中的一个值,你可以用“setValue()”设置它,但你不能用“getValue”之类的东西来读取它,它必须由侦听器完成?

4

1 回答 1

0

问题源于两个事实:

  1. cdl.await()在主线程上运行,阻塞它直到通知。
  2. Firebase 回调也期望在主线程上发生。

由于 cdl.await() 发生在数据库回调之前,它会无限期地阻塞主线程,从而阻止回调发生(因为它排队等待在主线程上运行,而主线程被无限期地阻塞)。

解决方案是根本不使用 CountDownLatch。Firebase API 都是异步的,调用者应该期望结果在主线程上执行查询之后到达。执行应该从该回调继续,而不是从等待闩锁的东西开始。

于 2019-10-17T20:53:28.093 回答