如何在Java for Android中新创建的侦听器中修改外部布尔值
我有一个Android Fragment类,它有一个方法,可以在单击按钮后在外部firebase数据库上写一些东西
public class FR_Fragment extends Fragment implements View.OnClickListener {
public void onClick(View view) {
boolean writingSuccessfull = false;
boolean writingNotSuccessfull = false;
firebase_DB.child(id).setValue(currentOrder).addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
writingSuccessfull = true;
writingNotSuccessfull = false;
Log.e("dbTAG", "Data successfully written.");
}
else {
writingSuccessfull = false;
writingNotSuccessfull = true;
Log.e("dbTAG", task.getException().getMessage());
}
}
});
}
}
但是,我不知何故无法访问布尔变量writingSuccessfull
和writingNotSuccessfull
,以及我在OnCompleteListener中的方法onClick中定义的布尔变量。通过显示的代码,我得到一个错误“变量'writingSuccessfull'是从内部类中访问的,需要是final或有效final”
当我让Android Studio解决此问题时,代码如下所示:
public class FR_Fragment extends Fragment implements View.OnClickListener {
public void onClick(View view) {
final boolean[] writingSuccessfull = { false };
final boolean[] writingNotSuccessfull = { false };
firebase_DB.child(id).setValue(currentOrder).addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
writingSuccessfull[0] = true;
writingNotSuccessfull[0] = false
Log.e("dbTAG", "Data successfully written.");
}
else {
writingSuccessfull[0] = false;
writingNotSuccessfull[0] = true
Log.e("dbTAG", task.getException().getMessage());
}
}
});
}
}
现在我可以执行代码了,但是布尔值不会改变,即使监听器中的代码被执行了。我还尝试了在布尔变量之前不使用“final”的方法。但这并没有改变任何事情。我无法修改此侦听器中的布尔变量。但这是我需要做的事情,因为我想知道数据是否已成功写入数据库
你知道我为什么会遇到这个问题以及如何解决吗?我将感谢你的每一句评论
更新:以下是使用volatile和AtomicBooleas更新的代码:
public class FR_Fragment extends Fragment implements View.OnClickListener {
private volatile AtomicBoolean writingOrderToTheDatabaseWasSuccessful;
private volatile AtomicBoolean writingOrderToTheDatabaseWasNotSuccessful;
...
public void onClick(View view) {
int internalCounterAttempsWriteDataInTheFBDatabase =0;
writingOrderToTheDatabaseWasSuccessful = new AtomicBoolean (false);
writingOrderToTheDatabaseWasNotSuccessful = new AtomicBoolean (false);
while(writingOrderToTheDatabaseWasSuccessful.get() == false && writingOrderToTheDatabaseWasNotSuccessful.get()==false) {
internalCounterAttempsWriteDataInTheFBDatabase++;
Log.e("LogTag", "internalCounterAttempsWriteDataInTheFBDatabase: " +internalCounterAttempsWriteDataInTheFBDatabase );
Log.e("LogTag", "writingOrderToTheDatabaseWasSuccessful: " + writingOrderToTheDatabaseWasSuccessful.get());
Log.e("LogTag", "writingOrderToTheDatabaseWasNotSuccessful: " + writingOrderToTheDatabaseWasNotSuccessful.get());
DatabaseReference rootRef = FirebaseDatabase.getInstance("https://drink-server-db-default-rtdb.europe-west1.firebasedatabase.app").getReference();
DatabaseReference ordersRef = rootRef.child("orders");
String id =...;
FirebaseDBItem_Order currentOrder = ...;
ordersRef.child(id).setValue(currentOrder).addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
writingOrderToTheDatabaseWasSuccessful.set(true);
writingOrderToTheDatabaseWasNotSuccessful.set(false);
Log.e("dbTAG", "Data successfully written.");
Log.e("LogTag", "Listener: writingOrderToTheDatabaseWasSuccessful: " + writingOrderToTheDatabaseWasSuccessful.get());
Log.e("LogTag", "Listener: writingOrderToTheDatabaseWasNotSuccessful: " + writingOrderToTheDatabaseWasNotSuccessful.get());
} else {
Log.e("dbTAG", task.getException().getMessage());
}
}//end method onComplete
});//end addOnCompleteListener
if (internalCounterAttempsWriteDataInTheFBDatabase >=10) {
writingOrderToTheDatabaseWasNotSuccessful.set(true);
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}//end while loop
Log.e("LogTag", "EndWhile: writingOrderToTheDatabaseWasSuccessful: " + writingOrderToTheDatabaseWasSuccessful.get());
Log.e("LogTag", "EndWhile: writingOrderToTheDatabaseWasNotSuccessful: " + writingOrderToTheDatabaseWasNotSuccessful.get());
//Show a toast about the order
if (writingOrderToTheDatabaseWasSuccessful.get() ==true) {
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(getContext(), getString(R.string.message_orderSubmittedSuccessfully), duration);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
}
if (writingOrderToTheDatabaseWasNotSuccessful.get() ==true) {
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(getContext(), getString(R.string.message_orderSubmittedNotSuccessfully), duration);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
}
Navigation.findNavController(...);
}//end method onClick
}//end class
问题是onComplete方法的asnychronous调用。更改布尔值的代码不会像在异步调用的onComplete方法中那样立即调用。这意味着在我的示例中,onComplete方法中的代码只是在10次while循环迭代之后调用,而不是在预期的循环期间调用。现在最大的问题是如何在while循环期间调用onComplete方法中的任何代码
更新:以下是运行代码时logcat的(相关)输出:
E/LogTag: internalCounterAttempsWriteDataInTheFBDatabase: 1
writingOrderToTheDatabaseWasSuccessful: false
writingOrderToTheDatabaseWasNotSuccessful: false
E/LogTag: internalCounterAttempsWriteDataInTheFBDatabase: 2
E/LogTag: writingOrderToTheDatabaseWasSuccessful: false
writingOrderToTheDatabaseWasNotSuccessful: false
E/LogTag: internalCounterAttempsWriteDataInTheFBDatabase: 3
writingOrderToTheDatabaseWasSuccessful: false
writingOrderToTheDatabaseWasNotSuccessful: false
E/LogTag: internalCounterAttempsWriteDataInTheFBDatabase: 4
E/LogTag: writingOrderToTheDatabaseWasSuccessful: false
writingOrderToTheDatabaseWasNotSuccessful: false
E/LogTag: internalCounterAttempsWriteDataInTheFBDatabase: 5
E/LogTag: writingOrderToTheDatabaseWasSuccessful: false
writingOrderToTheDatabaseWasNotSuccessful: false
E/LogTag: internalCounterAttempsWriteDataInTheFBDatabase: 6
writingOrderToTheDatabaseWasSuccessful: false
writingOrderToTheDatabaseWasNotSuccessful: false
E/LogTag: internalCounterAttempsWriteDataInTheFBDatabase: 7
E/LogTag: writingOrderToTheDatabaseWasSuccessful: false
writingOrderToTheDatabaseWasNotSuccessful: false
E/LogTag: internalCounterAttempsWriteDataInTheFBDatabase: 8
writingOrderToTheDatabaseWasSuccessful: false
E/LogTag: writingOrderToTheDatabaseWasNotSuccessful: false
E/LogTag: internalCounterAttempsWriteDataInTheFBDatabase: 9
writingOrderToTheDatabaseWasSuccessful: false
writingOrderToTheDatabaseWasNotSuccessful: false
E/LogTag: internalCounterAttempsWriteDataInTheFBDatabase: 10
E/LogTag: writingOrderToTheDatabaseWasSuccessful: false
E/LogTag: writingOrderToTheDatabaseWasNotSuccessful: false
E/LogTag: EndWhile: writingOrderToTheDatabaseWasSuccessful: false
EndWhile: writingOrderToTheDatabaseWasNotSuccessful: true
E/dbTAG: Data successfully written.
E/LogTag: Listener: writingOrderToTheDatabaseWasSuccessful: true
Listener: writingOrderToTheDatabaseWasNotSuccessful: false
E/dbTAG: Data successfully written.
E/LogTag: Listener: writingOrderToTheDatabaseWasSuccessful: true
Listener: writingOrderToTheDatabaseWasNotSuccessful: false
E/dbTAG: Data successfully written.
E/LogTag: Listener: writingOrderToTheDatabaseWasSuccessful: true
Listener: writingOrderToTheDatabaseWasNotSuccessful: false
E/dbTAG: Data successfully written.
E/LogTag: Listener: writingOrderToTheDatabaseWasSuccessful: true
E/LogTag: Listener: writingOrderToTheDatabaseWasNotSuccessful: false
E/dbTAG: Data successfully written.
E/LogTag: Listener: writingOrderToTheDatabaseWasSuccessful: true
Listener: writingOrderToTheDatabaseWasNotSuccessful: false
E/dbTAG: Data successfully written.
E/LogTag: Listener: writingOrderToTheDatabaseWasSuccessful: true
Listener: writingOrderToTheDatabaseWasNotSuccessful: false
E/dbTAG: Data successfully written.
E/LogTag: Listener: writingOrderToTheDatabaseWasSuccessful: true
Listener: writingOrderToTheDatabaseWasNotSuccessful: false
E/dbTAG: Data successfully written.
E/LogTag: Listener: writingOrderToTheDatabaseWasSuccessful: true
E/LogTag: Listener: writingOrderToTheDatabaseWasNotSuccessful: false
E/dbTAG: Data successfully written.
E/LogTag: Listener: writingOrderToTheDatabaseWasSuccessful: true
E/LogTag: Listener: writingOrderToTheDatabaseWasNotSuccessful: false
E/dbTAG: Data successfully written.
E/LogTag: Listener: writingOrderToTheDatabaseWasSuccessful: true
Listener: writingOrderToTheDatabaseWasNotSuccessful: false
结果是该项在firebase数据库中保存了10次。我想要的是尝试在firebase db中存储该项一次。如果这是成功的,循环应该停止,应该有一个祝酒词告诉它是成功的。如果未成功,循环应尝试10次(延迟1秒)。如果即使在10次尝试之后,该项仍无法存储在firebase数据库中,则应停止循环,并出现toast消息,告知无法存储该项
# 1 楼答案
也许你不应该使用布尔值,你可以在任务成功时使用return方法,并在while(true)或for循环中执行setValue(),这样当任务成功时,循环将停止工作,或者当循环达到她的极限时。 像这样:
# 2 楼答案
创建扩展AndroidViewModel的自定义类
然后在片段中使用这个自定义viewmodel类来观察值的变化
这是MVVM体系结构的一个简单片段。希望它现在能起作用。谢谢