每次尝试从Firestore数据库中按下按钮时,我都试图更新一个变量,但是问题是,每当我启动应用程序时,我第一次获得null时,当我按下按钮时,第二次正常工作。
似乎我第一次按下按钮时变量未正确初始化。我不知道。
private String name;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.friendsystem_add);
//[Initializing UI Components]
emailToAdd = findViewById(R.id.friend_rq_name);
//[Getting variable]
Button send = findViewById(R.id.friend_rq_send);
send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final String email = emailToAdd.getText().toString();
//check if user exists or not
doesExist(email);
}
Toast.makeText(AddFriend.this, name, Toast.LENGTH_SHORT).show();
这是我的方法:
private void doesExist(String email) {
//sending our friend request to database
db.collection("Users")
//query
.whereEqualTo("email", email)
//getting results
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
@Override
public void onComplete(@NonNull Task<QuerySnapshot> task) {
//check if task is successfull
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document : task.getResult()) {
//getting target account name
name = document.getString("name");
}
}
}
});
}
这是我的完整代码: https://gist.github.com/arshiyanine/dc16f187d5bcaaaefddd8e38fd8f82c1 谢谢。
答案 0 :(得分:0)
数据是从Cloud Firestore异步加载的,开始加载后的代码将继续运行。然后,在加载数据后,SDK会调用您的完成处理程序。这意味着该数据仅在onComplete
方法的内部中可用。要了解这意味着什么,请使用一些如下的日志语句运行代码:
System.out.println("Before starting query");
db.collection("Users")
.whereEqualTo("email", email)
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
@Override
public void onComplete(@NonNull Task<QuerySnapshot> task) {
System.out.println("Got documents");
}
});
System.out.println("After starting query");
如果运行此代码,则输出为:
开始查询之前
开始查询后
获得的文件
这可能不是您期望的顺序。但这很好地解释了为什么吐司不显示数据库名称:数据尚未加载!
这意味着需要从数据库中获取数据的任何代码都必须在onComplete()
方法的内部中进行调用。最简单的解决方案是使用该方法简单地显示烤面包:
private void doesExist(String email) {
db.collection("Users")
.whereEqualTo("email", email)
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
@Override
public void onComplete(@NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document : task.getResult()) {
name = document.getString("name");
}
Toast.makeText(AddFriend.this, name, Toast.LENGTH_SHORT).show();
}
}
});
}
这非常简单,但是会使您的doesExist
的可重用性降低。如果这是一个问题,请考虑创建一个自定义回调。与Task
类似,但在这里专门讨论您的用例。一个简单的例子:
public interface GetUserNameCallback {
void onUserExists(String name);
void onUserDoesNotExist();
}
private void doesExist(String email, UserExistsCallback callback) {
db.collection("Users")
.whereEqualTo("email", email)
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
@Override
public void onComplete(@NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
String name;
for (QueryDocumentSnapshot document : task.getResult()) {
name = document.getString("name");
}
callback.onUserExists(name);
}
else {
callback.onUserDoesNotExist();
}
}
});
}
然后像这样调用它:
doesExist(email, new UserExistsCallback() {
@Override
public void onUserExists(String name) {
Toast.makeText(AddFriend.this, name, Toast.LENGTH_SHORT).show();
}
@Override
public void onUserDoesNotExist() {
Toast.makeText(AddFriend.this, "User "+email+" does not exist", Toast.LENGTH_SHORT).show();
}
});
有关更多示例,请参见: