Java 事件侦听器在被删除后侦听
我班上有很多事件侦听器,早些时候我问过如何在这些侦听器发生一次后杀死它们,我已经解决了这个问题 它在某些情况下有效,但在另一些情况下我有问题。例如,我有一个具有事件侦听器的方法Java 事件侦听器在被删除后侦听,java,android,firebase,firebase-realtime-database,Java,Android,Firebase,Firebase Realtime Database,我班上有很多事件侦听器,早些时候我问过如何在这些侦听器发生一次后杀死它们,我已经解决了这个问题 它在某些情况下有效,但在另一些情况下我有问题。例如,我有一个具有事件侦听器的方法 private void startGame() { HomePage.getCurrentGameID(new HomePage.CallbackID() { @Override public void onSuccess(final String currentGame
private void startGame() {
HomePage.getCurrentGameID(new HomePage.CallbackID() {
@Override
public void onSuccess(final String currentGameID) {
games.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.child(currentGameID).getValue().equals(1)) {
getResults();
Log.i("FlipCoin", "``startGame() happened");
} else {
return;
}
games.removeEventListener(this);
}
}
我有启动游戏的方法,在onDataChange()
结束时,我有games.removeEventListener(这个)
。但是有时候,即使在执行了这个之后,它仍然会运行代码,我知道这一点,因为每次该方法发生时,它都会记录到LogCat
我的代码中只有一个实例调用了startGame()
,该实例就在这个计时器中
private void runCounter() {
final Runnable counter = new Runnable() {
@Override
public void run() {
Log.i("FlipCoin", "``runCounter() happened");
startGame();
}
}
};
counter.run();
}
我去掉了许多不必要的代码,因此这些方法可能没有太多实际意义,但它们正被用作解决我的问题的示例
无论如何,正如您在runCounter()方法中所看到的,它会像应该的那样调用startGame()
,并且我在该方法中还有一个日志,可以让我知道何时调用此runCoutner()
方法
奇怪的是runCounter()
方法在logcat中只记录了一次,但它一直记录startGame()
,即使我在代码中只调用了一次,并且在方法的末尾删除了侦听器
为什么会发生这种事,我超级困惑
我正在使用的Runnable(与问题无关)
你用错了
如果只想侦听该值一次,然后删除侦听器,请使用:
addListenerForSingleValueEvent
,您可能应该在addValueEventListener
之前添加日志,以了解它是否被多次添加。根据此代码,如果removeEventListener
实现正确,则不应发生这种情况。为什么不使用addListenerForSingleValueEvent
,其全部目的是只侦听一次?而且完全不需要在运行计数器中运行。如果你只调用startName(),你会得到完全相同的效果。@DougStevenson将其转换为addListenerForSingleValueEvent
,会出现一些问题,如果你仔细阅读了我的帖子,你就会知道我去掉了代码来简化问题,Runnable确实有一个目的。我很好奇这个Runnable的实际用途是什么,现在它的行为与根本没有它相比。您通常只将Runnable与新线程、某个线程池或执行器结合使用。我也很好奇为什么addListenerForSingleValueEvent不适合您,因为它是SDK的核心功能。如果你正确使用它,它应该不会有问题。这意味着你的代码不止一次地调用这个方法。我的代码中只有一个点,我已经看过很多次了,这个方法被调用了。调用该方法的Runnable也只被调用一次。代码中只有一个调用并不意味着代码不会被多次调用。。。你可以开始组织你的代码,这比你最终会发现的bug还要混乱。您创建了许多可运行的并在同一个线程中执行它们。。。这是毫无意义的。创建不必要的注释性类是一种糟糕的做法。另外,对于新主页.CallbackID()
的作用没有任何解释。。。您使用get
方法并将某个内容作为参数传递。。。这是一个基本的代码设计,如果你仍然无法理解为什么要多次调用,简单的调试,看看堆栈跟踪哪个方法在调用它,就像我在我的帖子中说的,我拿出了很多代码只是为了将问题简化到核心。所有看起来毫无意义的代码实际上都不是毫无意义的。
private void runCounter() {
final TextView headsOrTails = findViewById(R.id.HeadsOrTails);
final Handler handler = new Handler();
final AtomicInteger n = new AtomicInteger(3);
final Runnable counter = new Runnable() {
@Override
public void run() {
headsOrTails.setText("Flipping in: " + Integer.toString(n.get()) + " seconds");
if (n.getAndDecrement() >= 1)
handler.postDelayed(this, 1000);
else {
headsOrTails.setText("Flipping");
Log.i("FlipCoin", "``runCounter() happened");
startGame();
}
}
};
counter.run();
}