Быстрое изучение кода addListenerForSingleValueEvent показывает, почему это не удается:
Firebase добавляет свой собственный прослушиватель событий, который удаляется при вызове onDataChanged. Таким образом, в addListenerForSingleValueEvent нет ничего особенного, и я предполагаю, что мы можем обойти проблему таким способом (используя обычный addValueEventListener):
DatabaseReference ref = db.getReference("blabla");
oneshotlistener = new ValueEventListener()
{
@Override
public void onDataChange(@NonNull DataSnapshot snapshot)
{
snapshot.getRef().removeEventListener(this);
Log.v("FIREBASE LISTEN", "ONE SHOT LISTENER TRIGGERED");
if (snapshot.exists())
{
String s = snapshot.getValue(String.class);
Log.v("FIREBASE LISTEN", "RESULT: " + s);
}
}
@Override
public void onCancelled(@NonNull DatabaseError error)
{
Log.v("LISTEN", "DB FAIL");
}
};
ref.addValueEventListener(oneshotlistener);
ref.removeEventListener(oneshotlistener); //remove immediately for test
Тесты подтверждают, что слушатель никогда не запускается. Теперь можно разработать процедуру тайм-аута, чтобы удалить слушателя и вызвать ошибку. Также слушатель может быть удален в onPause (), поэтому неожиданные события onDataChanged не возникают, если приложение приостановлено / возобновлено. Тем не менее, было бы неплохо, если бы в Firebase была встроена эта функция. Имейте функцию, которая позволяет устанавливать тайм-аут прослушивания в миллисекундах, а для слушателей, зарегистрированных с помощью addListenerForSingleValueEvent, есть дополнительный вызов интерфейса, например:
db.setTimeout(ms);
DatabaseReference ref = db.getReference("blablalba");
oneshotlistener = new ValueEventListener()
{
@Override
public void onDataChange(@NonNull DataSnapshot snapshot)
{
Log.v("FIREBASE LISTEN", "ONE SHOT LISTENER TRIGGERED");
if (snapshot.exists())
{
String s = snapshot.getValue(String.class);
Log.v("FIREBASE LISTEN", "RESULT: " + s);
}
}
@Override
public void onCancelled(@NonNull DatabaseError error)
{
Log.v("LISTEN", "DB FAIL");
}
@Override
public void onTimeout()
{
Log.v("LISTEN", "OP TIMEDOUT");
//take action
}
};
ref.addListenerForSingleValueEvent(oneshotlistener);